#applications #postgresql #orm #rapid #web-framework #web-apps #rest

bin+lib tailwag

这是 Tailwag 套件的主 crate,一个包含所有功能的实验性框架,用于构建原型应用

2 个版本

0.1.1 2024年6月13日
0.1.0 2024年6月13日

#637数据库接口

MIT/Apache

47KB
55

尾摇 - 快速 Rust 工具包

这个仓库汇集了各种 Rust 库,旨在快速创建 REST API 和数据应用。尾摇的最终目标是实现新服务的零到生产开发部署,并使用合理的默认值。

当前的开发版本支持创建由原始数据类型、时间戳和 UUID 组成的数据类型的 REST 服务和 Postgres 数据库。它目前不支持连接或嵌套数据结构,除了有限的单对单数据结构支持。

子 crate

  • tailwag_orm: 一个将 Rust 数据类型映射到数据库查询或其他数据存储的 ORM。它目前支持创建新的 Postgres 表和 CRUD 操作,并实验性地支持在表更改时迁移表。

  • tailwag_forms _: 用于表示创建或编辑数据的表单结构的 crate。它导出格式可由 tailwag_react_manager 读取,这是一个与该工具包配对以生成管理表单的 NextJS 应用。

  • tailwag_web_application: 这是 Tailwag 当前的主要交互方式。我开始在 axum 上构建这个框架,它本身是一个优秀的网络框架,但在尝试克服一些限制时,我最终实现了自己的 HTTP 处理器,并最终将 axum 作为依赖项删除。

项目状态:实验性

这个项目正在我的业余时间积极开发,尽管它还处于早期阶段。它目前有大量的 unwrap() 调用,TODO 注释和未优化的代码。我已经努力在代码注释中记录已知的技术债务。特别是宏有点奇怪(见常见问题解答 - “宏怎么了?”)。

我对错误处理进行了最近的一些改进,并希望很快消除所有 .unwrap() 调用,这些调用目前在某些情况下导致意外崩溃。

它目前也是单线程的,一次只能处理一个请求,这是由于底层HTTP实现处于WIP状态。

入门指南

目前Tailwag最有用的功能是搭建一组定义数据类型的REST API。以下代码示例将搭建一个具有完整CRUD操作的Item结构体的API。

注意 为了运行此示例,您需要在本地上运行Postgres实例。如果没有找到环境配置,Tailwag将在开发模式下使用postgres:postgres作为用户名:密码。

docker run --name some-postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -p 5432:5432 postgres

最小工作示例

以下是一个基于Tailwag的整个Rust程序。这段代码创建了一个运行在https://127.0.0.1:8081上的REST web服务,其中/todo/端点支持通过POSTGETPATCHDELETE HTTP方法执行CRUD操作。也支持/todo/{id}的GET操作。

请注意,tailwag有一些依赖项,这些依赖项不是由tailwag当前重新导出的。让我们从头开始创建一个项目,以获取第一个Tailwag应用程序。

首先,创建一个新的Cargo项目

cargo new my_tailwag_app
cd my_tailwag_app

接下来添加我们的依赖项

cargo add tailwag
cargo add serde --features derive # Required for just about all tailwag operations.
cargo add chrono # If you need datetime support.
cargo add uuid # Required for tailwag database support.
cargo add sqlx # Required for database communication with Postgres.
cargo add tokio --features full # Required for the async runtime.

现在我们的应用程序

use tailwag::macros::derive_magic;
use tailwag::web::application::WebService;

#[tokio::main]
async fn main() {
    derive_magic! {
        struct Todo {
            id: uuid::Uuid, // Note: Currently all data types MUST have an `id` of type `uuid::Uuid`. A future version will remove this limitation.
            title: String,
            description: String,
            due_date: chrono::NaiveDateTime,
        }
    }
    WebService::builder("Todo Service")
        .with_resource::<Todo>()
        .build_service()
        .run()
        .await
        .expect("Web service crashed.");
}
The `derive_magic!` macro derives a lot of traits that the `WebService` struct
uses for building routes, postgres data, etc.

别忘了启动你的postgres实例

docker run --name some-postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -p 5432:5432 postgres

现在运行该服务

cargo run

使用一些TODO项打击端点

curl -X POST https://127.0.0.1:8081/todo \
    -H "Content-Type: application/json" \
    -d '{"title": "Add multithread support", "description": "To be viable in a Production environment, tailwag needs to support multiple concurrent requests.", "due_date": "2024-06-13T00:00:00"}'

curl -X POST https://127.0.0.1:8081/todo \
    -H "Content-Type: application/json" \
    -d '{"title": "Remove id requirement", "description": "Update tailwag to allow more flexibility for table primary keys.", "due_date": "2024-06-13T00:00:00"}'

现在让我们获取所有TODO项

curl https://127.0.0.1:8081/todo | jq
[
  {
    "id": "68e20f9e-0fbd-4bda-9095-b2749948579d",
    "title": "Add multithread support",
    "description": "To be viable in a Production environment, tailwag needs to support multiple concurrent requests.",
    "due_date": "2024-06-13T00:00:00"
  },
  {
    "id": "505180d4-eb25-4352-8599-6e4d69bd2806",
    "title": "Remove id requirement",
    "description": "Update tailwag to allow more flexibility for table primary keys.",
    "due_date": "2024-06-13T00:00:00"
  }
]

或者只是一个单个TODO

curl https://127.0.0.1:8081/todo | jq
{
  "id": "68e20f9e-0fbd-4bda-9095-b2749948579d",
  "title": "Add multithread support",
  "description": "To be viable in a Production environment, tailwag needs to support multiple concurrent requests.",
  "due_date": "2024-06-13T00:00:00"
}

更多详细示例可以在/examples文件夹中找到。还有更多详细示例在tailwag_web_service crate中。

我如何支持这个项目?

  1. 使用它! - 请尝试使用API构建一些项目,并将其用于实际测试。对于您遇到的任何挑战或错误,请提交问题。如果您有不受支持的用例,请将其作为问题提交。

  2. 星级 & 点赞 - 考虑给项目加星或关注,并且/或者关注我(@nikwithak)在GitHub上。这些都是零成本的方式,可以扩展我的工作受众。

  3. 捐赠或赞助 - 这个项目完全是我空闲时间写的,您的捐赠使我能够继续投入时间和精力来维护它并开发新功能。接受并感谢所有捐赠金额。我非常乐意能够全职专注于这个项目,您的捐赠帮助实现这一目标。

    如果您想赞助这个项目,请发送电子邮件至[email protected],我很乐意聊天!

原则 [有偏见的框架]

Tailwag是一个有偏见的框架,将引导你进入特定的模式。我计划不久后发布《Tailwag Book》,这是一本免费的开源用户指南,用于使用Tailwag构建应用程序。

Tailwag侧重于以下原则,作为您基本应用程序的构建块

  • 定义您的数据

    • 数据模型是应用程序最重要的部分,因此保持定义的一致性和易于修改至关重要。这个框架旨在使定义应用程序所需的核心数据结构变得简单和快速,并与其他系统部分共享该定义。
    • 操作定义在对象或一组对象上。这些作为webhooks / API端点公开,以触发操作。
    • 逻辑和
  • 关注人体工程学 - Tailwag 极度依赖特性和派生宏。目标是实现一般情况的合理默认设置,以便零努力即可获得一个标准、实用的应用,同时通过特性实现方便地覆盖自定义行为。一般来说,我尽量避免了执行过多魔法的程序性(非派生)宏。

常见问题解答

问题:为什么不使用现有的crate,如 axumactix-webdieselyew<其他库>

答案:我坚信实践是提高生产力的工具。我最初创建这些库是为了自学练习,随着时间的推移,它们已经变得更有用。

问题:宏crate有什么问题?

答案:我最初编写的宏是一团糟,代码像意大利面一样乱。我一直在逐渐简化我的编写方式,以便使它们更易于阅读/维护。长话短说:它们现在一团糟。

目前,我为具有自定义宏的crate创建了两个宏子crate,一个用于导出,一个用于逻辑。最初我认为这将使宏的重用和测试更容易,考虑到编译器强制要求proc_macro导出必须是一个完全独立的crate,但实际情况是,我只是在更改宏时创建了一个令人烦恼的障碍。我将在未来重构并简化这些宏。

问题:为什么做出某些决定?

答案:有时做出决定的理由只是因为当时这样做是合理的。框架的一些部分我已经重建了几次,有些我一开始做得很满意,而有些我希望我当初能做得不同,但现在已经很难更改。这就是所有软件项目的斗争。

问题:我还有另一个问题。

答案:请提交问题发电子邮件给我

我能否在生产中使用Tailwag?

答案:你可以根据自己的需要使用Tailwag,尽管目前它有一些已知的限制。它提供“现状”,不提供任何类型的保证。如果您在生产应用中使用它,请确保进行充分的测试。

许可证

版权(c)2024 Nik Gilmore (@nikwithak)

特此免费授予任何获得此软件及其相关文档副本(以下简称“软件”)的个人,在不受限制的情况下处理软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件副本的权利,并允许向软件提供者提供软件的个人这样做,前提是遵守以下条件

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

软件按“现状”提供,不提供任何类型的保证,无论是明示的还是暗示的,包括但不限于适销性、特定用途适用性和非侵权性保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任负责,无论这些责任是因合同、侵权或其他方式引起的,与软件或软件的使用或其他交易有关。

依赖关系

~77MB
~1.5M SLoC