fix add_fields population

This commit is contained in:
Sandipsinh Rathod 2024-12-22 15:28:50 -05:00
parent c5a178da1a
commit d3658fd6f0
12 changed files with 227 additions and 67 deletions

1
Cargo.lock generated

@ -184,6 +184,7 @@ dependencies = [
"anyhow",
"base64",
"convert_case",
"derive_setters",
"lazy_static",
"macros",
"oapi",

@ -22,6 +22,7 @@ lazy_static = "1.5.0"
base64 = "0.22.1"
strum_macros = "0.26.4"
macros = {path = "macros"}
derive_setters = "0.1.6"
[workspace]
members = [".", "macros"]

@ -42,7 +42,6 @@ impl Ord for Interface {
pub struct Record {
pub name: String,
pub fields: BTreeSet<Field>,
pub added_fields: BTreeSet<Field>,
}
impl PartialOrd for Record {
@ -85,7 +84,7 @@ pub struct Parameter {
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct Field {
pub name: String,
pub field_type: WitType,
pub field_type: String,
}
impl PartialOrd for Field {

@ -1,45 +1,101 @@
use std::collections::BTreeSet;
use base64::Engine;
use tailcall_valid::{Valid, Validator};
use crate::config::config::{Config, Field, Interface, Record};
use crate::config::schema_document::{SchemaDocument, Field, Interface, Record};
use crate::config::wit_types::WitType;
use crate::merge_right::MergeRight;
use crate::tryfold::TryFold;
pub fn fix_args(config: Config) -> Valid<Config, anyhow::Error, anyhow::Error> {
pub fn fix_args(config: SchemaDocument) -> Valid<SchemaDocument, anyhow::Error, anyhow::Error> {
Valid::succeed(config)
.and_then(|mut config| {
Valid::from_iter(config.interfaces.iter(), |interface| {
Valid::from_iter(interface.records.iter(), |record| {
Valid::from_iter(record.fields.iter(), |field| {
Valid::from_iter(config.interfaces.iter().cloned().collect::<Vec<_>>(), |mut interface| {
Valid::from_iter(interface.records.iter().cloned(), |mut record| {
Valid::from_iter(record.fields.iter().cloned(), |field| {
if !field.field_type.is_kind_of_primitive() {
fix_field()
.try_fold(&(&config, interface, record, &field, &field.field_type), interface.clone())
.and_then(|new_interface| {
Valid::succeed(Some(new_interface))
.try_fold(&(&config, &interface, &record, &field, &field.field_type), Field::default())
.and_then(|field| {
Valid::succeed(Some(field))
})
} else {
}else {
Valid::succeed(None)
}
})
})
}).and_then(|x| {
let x = x.into_iter().flatten().into_iter().flatten().filter_map(|x| x).collect::<Vec<_>>();
}).and_then(|v| {
let fields = v.into_iter().filter_map(|x| x).collect();
record.added_fields = fields;
let mut map = BTreeSet::new();
for interface in x {
map.insert(interface);
Valid::succeed(record)
})
}).and_then(|records| {
interface.records = records.into_iter().collect();
Valid::succeed(interface)
})
}).and_then(|interfaces| {
config.interfaces = interfaces.into_iter().collect();
/*for interface in interfaces {
if let Some(interface) = config.interfaces.iter().find(|i| i.name == interface.name) {
for record in interface.records {
if let Some(mut record) = interface.records.iter().find(|r| r.name == record.name).cloned() {
for field in record.fields {
if let Some(field) = record.fields.iter().find(|f| f.name == field.name) {
let mut new_field = field.clone();
new_field.field_type = field.field_type.clone().merge_right(new_field.field_type.clone());
record.fields.remove(&field);
record.fields.insert(new_field);
}
}
}
}
}else {
config.interfaces.insert(interface);
}
}*/
/* let mut new_interfaces = BTreeSet::new();
for mut interface in config.interfaces {
let mut new_records = BTreeSet::new();
for mut record in interface.records {
let mut new_fields = BTreeSet::new();
for mut field in record.fields {
let mut new_field = interfaces
.iter()
.find(|i| i.name == interface.name).and_then(|interface| interface.records.iter().find(|r| r.name == record.name).and_then(|record|record.fields.iter().find(|f| f.name == field.name)))
.unwrap_or(&field)
.clone();
new_field = new_field.merge_right(field);
new_fields.insert(new_field);
}
record.fields = new_fields;
new_records.insert(record);
}
interface.records = new_records;
new_interfaces.insert(interface);
}
config.interfaces = config.interfaces.merge_right(map);
config.interfaces = new_interfaces;*/
// config.interfaces = config.interfaces.merge_right(map);
Valid::succeed(config)
})
})
}
fn fix_field<'a>() -> TryFold<'a, (&'a Config, &'a Interface, &'a Record, &'a Field, &'a WitType), Interface, anyhow::Error> {
TryFold::<(&Config, &Interface, &Record, &Field, &WitType), Interface, anyhow::Error>::new(move |(config, interface, rec, field, wit), mut o| {
/*
interface types {
record error { error: { message: string, details: list<{ field: string, message: string }>, code: string } }
record todo { completed: bool, created-at: string, description: string, due-date: string, id: string, title: string, updated-at: string, user-id: string }
record todo-create { description: string, due-date: string, title: string, user-id: string }
record todo-list { data: list<{ id: string, user-id: string, title: string, due-date: string, created-at: string, updated-at: string, completed: bool, description: string }>, metadata: { total: s32, offset: s32, limit: s32 } }
record todo-response { data: { id: string, user-id: string, title: string, due-date: string, created-at: string, updated-at: string, completed: bool, description: string } }
record todo-update { completed: bool, description: string, due-date: string, title: string }
}
*/
fn fix_field<'a>() -> TryFold<'a, (&'a SchemaDocument, &'a Interface, &'a Record, &'a Field, &'a WitType), Field, anyhow::Error> {
TryFold::<(&SchemaDocument, &Interface, &Record, &Field, &WitType), Field, anyhow::Error>::new(move |(config, interface, rec, field, wit), mut o| {
match &wit {
WitType::Option(x) => {
return fix_field().try_fold(&(*config, *interface, *rec, *field, x), o);
@ -63,30 +119,23 @@ fn fix_field<'a>() -> TryFold<'a, (&'a Config, &'a Interface, &'a Record, &'a Fi
WitType::Tuple(x) => {
// TODO: Fix the possible conflicts here
return Valid::from_iter(x.iter(), |x| fix_field().try_fold(&(*config, *interface, *rec, *field, x), o.clone()))
.and_then(|v| Valid::succeed(v.into_iter().fold((*interface).clone(), |mut a, b| {
a.records.extend(b.records);
a
.and_then(|v| Valid::succeed(v.into_iter().fold((*field).clone(), |mut a, b| {
a.merge_right(b)
})));
}
WitType::Record(records) => {
let field_name = if field.name.is_empty() {
base64::prelude::BASE64_STANDARD.encode(field.name.as_bytes())
}else {
} else {
field.name.clone()
};
let name = format!("{}-{}", rec.name, field_name);
let new_field = Field {
name,
field_type: WitType::Record(records.clone()),
};
let mut rec = (*rec).clone();
rec.added_fields.insert(new_field);
// let mut filtered_records = o.records.into_iter().filter(|r| r.name == rec.name).collect::<Vec<_>>();
// filtered_records.push(rec);
o.records.remove(&rec);
o.records.insert(rec);
Valid::succeed(o)
Valid::succeed(new_field)
}
// Ideally this case should never happen,
// but we should always throw an error to avoid infinite recursion

@ -1,12 +1,12 @@
use std::collections::BTreeSet;
use anyhow::{anyhow, Error};
use tailcall_valid::{Valid, Validator};
use crate::config::config::{Config, Field, Interface, Record};
use crate::config::schema_document::{SchemaDocument, Field, Interface, Record};
use crate::config::wit_types::WitType;
use crate::ser::OpenApiSpec;
pub fn handle_types(config: Config, spec: &OpenApiSpec) -> Valid<Config, Error, Error> {
Valid::succeed(config).and_then(|mut config: Config| {
pub fn handle_types(config: SchemaDocument, spec: &OpenApiSpec) -> Valid<SchemaDocument, Error, Error> {
Valid::succeed(config).and_then(|mut config: SchemaDocument| {
Valid::from_option(spec.components.as_ref(), anyhow!("Components are required"))
.and_then(|v| Valid::from_option(v.schemas.as_ref(), anyhow!("Schemas are required")))
.and_then(|schemas| {

@ -1,5 +1,7 @@
pub mod config;
pub mod schema_document;
pub mod wit_types;
pub mod to_wit;
pub mod fixargs;
pub mod handle_files;
pub mod config;
pub mod to_config;

@ -0,0 +1,101 @@
use std::collections::BTreeSet;
use serde::{Deserialize, Serialize};
use macros::MergeRight;
use crate::config::wit_types::WitType;
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct SchemaDocument {
pub package: String,
pub interfaces: BTreeSet<Interface>,
pub world: World,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct World {
pub name: String,
pub uses: Vec<UseStatement>,
pub imports: Vec<Interface>,
pub exports: Vec<Interface>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight, derive_setters::Setters)]
pub struct Interface {
pub name: String,
pub records: BTreeSet<Record>,
pub uses: Vec<UseStatement>,
pub functions: Vec<Function>,
}
impl PartialOrd for Interface {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.name.cmp(&other.name))
}
}
impl Ord for Interface {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.name.cmp(&other.name)
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct Record {
pub name: String,
pub fields: BTreeSet<Field>,
pub added_fields: BTreeSet<Field>,
}
impl PartialOrd for Record {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.name.cmp(&other.name))
}
}
impl Ord for Record {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.name.cmp(&other.name)
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct UseStatement {
pub name: String,
pub items: Vec<String>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct Function {
pub name: String,
pub parameters: Vec<Parameter>,
pub return_type: ReturnTy,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct ReturnTy {
pub return_type: String,
pub error_type: String,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct Parameter {
pub name: String,
pub parameter_type: String,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct Field {
pub name: String,
pub field_type: WitType,
}
impl PartialOrd for Field {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.name.cmp(&other.name))
}
}
impl Ord for Field {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.name.cmp(&other.name)
}
}

9
src/config/to_config.rs Normal file

@ -0,0 +1,9 @@
use tailcall_valid::Valid;
use crate::config::config::Config;
use crate::config::schema_document::SchemaDocument;
impl SchemaDocument {
pub fn to_config(&self) -> Valid<Config, anyhow::Error, anyhow::Error> {
todo!()
}
}

@ -1,4 +1,4 @@
use crate::config::config::{Config, Field, Function, Interface, Parameter, Record, ReturnTy, UseStatement, World};
use crate::config::schema_document::{SchemaDocument, Field, Function, Interface, Parameter, Record, ReturnTy, UseStatement, World};
use crate::config::wit_types::WitType;
use convert_case::{Case, Casing};
use std::collections::HashSet;
@ -41,8 +41,8 @@ fn generate_wit_name(name: &str) -> String {
final_name
}
impl ToWit for Config {
fn to_wit(&self) -> String {
impl SchemaDocument {
pub fn to_wit(&self) -> String {
let package = format!("package {};\n", generate_wit_name(&self.package));
let world = self.world.to_wit();
let interfaces = self
@ -56,8 +56,8 @@ impl ToWit for Config {
}
}
impl ToWit for World {
fn to_wit(&self) -> String {
impl World {
pub fn to_wit(&self) -> String {
if self == &World::default() {
return String::new();
}
@ -93,8 +93,8 @@ impl ToWit for World {
}
}
impl ToWit for Interface {
fn to_wit(&self) -> String {
impl Interface {
pub fn to_wit(&self) -> String {
let uses = self
.uses
.iter()
@ -126,8 +126,8 @@ impl ToWit for Interface {
}
}
impl ToWit for Record {
fn to_wit(&self) -> String {
impl Record {
pub fn to_wit(&self) -> String {
let fields = self
.fields
.iter()
@ -139,8 +139,8 @@ impl ToWit for Record {
}
}
impl ToWit for Field {
fn to_wit(&self) -> String {
impl Field {
pub fn to_wit(&self) -> String {
format!(
"{}: {}",
generate_wit_name(&self.name),
@ -150,8 +150,8 @@ impl ToWit for Field {
}
impl ToWit for Function {
fn to_wit(&self) -> String {
impl Function {
pub fn to_wit(&self) -> String {
let params = self
.parameters
.iter()
@ -174,8 +174,8 @@ impl ToWit for Function {
}
}
impl ToWit for ReturnTy {
fn to_wit(&self) -> String {
impl ReturnTy {
pub fn to_wit(&self) -> String {
if self.error_type.is_empty() {
self.return_type.clone()
} else {
@ -188,8 +188,8 @@ impl ToWit for ReturnTy {
}
}
impl ToWit for Parameter {
fn to_wit(&self) -> String {
impl Parameter {
pub fn to_wit(&self) -> String {
format!(
"{}: {}",
generate_wit_name(&self.name),
@ -198,8 +198,8 @@ impl ToWit for Parameter {
}
}
impl ToWit for UseStatement {
fn to_wit(&self) -> String {
impl UseStatement {
pub fn to_wit(&self) -> String {
format!(
"use {}.{{{}}};",
generate_wit_name(&self.name),
@ -212,8 +212,8 @@ impl ToWit for UseStatement {
}
}
impl ToWit for WitType {
fn to_wit(&self) -> String {
impl WitType {
pub fn to_wit(&self) -> String {
match self {
WitType::Bool => "bool".to_string(),
WitType::U8 => "u8".to_string(),
@ -274,7 +274,7 @@ impl ToWit for WitType {
.join(", ")
),
WitType::Handle(name) => format!("handle<{}>", generate_wit_name(name)),
WitType::TypeAlias(name, inner) => format!("type {} = {}", generate_wit_name(name), inner.to_wit()),
WitType::TypeAlias(name, inner) => format!("type {} = {}", generate_wit_name(name), inner.to_wit()),
}
}
}

@ -1,6 +1,5 @@
use serde::{Deserialize, Serialize};
use tailcall_valid::{Valid, Validator};
use crate::config::to_wit::ToWit;
use crate::ser::{OpenApiSpec, Schema};

@ -25,7 +25,7 @@ impl<A> MergeRight for Vec<A> {
impl<V> MergeRight for BTreeSet<V>
where
V: Ord,
V: Ord + MergeRight,
{
fn merge_right(self, mut other: Self) -> Self {
other.extend(self);

@ -1,13 +1,13 @@
use anyhow::Error;
use tailcall_valid::{Valid, Validator};
use crate::config::config::Config;
use crate::config::schema_document::SchemaDocument;
use crate::config::fixargs::fix_args;
use crate::config::handle_files::handle_types;
use crate::ser::OpenApiSpec;
fn to_config(spec: OpenApiSpec) -> Valid<Config, Error, Error> {
Valid::succeed(Config::default())
fn to_config(spec: OpenApiSpec) -> Valid<SchemaDocument, Error, Error> {
Valid::succeed(SchemaDocument::default())
.and_then(|config| handle_types(config, &spec))
.and_then(|config| fix_args(config))
}
@ -16,7 +16,6 @@ fn to_config(spec: OpenApiSpec) -> Valid<Config, Error, Error> {
mod t {
use tailcall_valid::Validator;
use crate::config::to_wit::ToWit;
use crate::proto::to_config;
use crate::ser::OpenApiSpec;
@ -30,8 +29,8 @@ mod t {
match res.as_mut() {
Ok(v) => {
println!("{}", serde_json::to_string_pretty(v).unwrap());
// v.package = "api:todos@1.0.0".to_string();
// println!("{}", v.to_wit());
v.package = "api:todos@1.0.0".to_string();
println!("{}", v.to_wit());
// let mut resolve = Resolve::new();
// resolve.push_str("foox.wit", &v.to_wit()).expect("TODO: panic message`");
// println!("{:#?}", resolve);