Skip to content

teodevgroup/teo

Repository files navigation

Teo



Schema-driven web server framework.

Quickstart   •   Official website   •   Docs   •   Blog   •   Discord

Introduction

Teo is schema-driven web server framework. The server side API is native to Rust, Node.js and Python.

Highlights & Features

  • Native to Rust, Node.js and Python
  • Innovative schema definition inspired by GraphQL and Prisma
  • Auto database migration
  • Supports MySQL, PostgreSQL, SQLite and MongoDB
  • Generated ORM types and interfaces
  • Generated query clients for frontend
  • Very efficient and performant
  • Data sanitization, transformation and validation
  • Builtin user sessions
  • Builtin permission check
  • First in last out middlewares
  • Custom route handlers
  • Generated customizable admin dashboard
  • Plays great with AI tools

Getting started

The fastest way to get started with Teo is by following the Quickstart guide.

Installation

Install Node.js edition.

npm install @teodevgroup/teo

Install Python edition.

pip install teo

Install Rust edition.

cargo install teo

Write a schema-only server

To write a server is quite simple with Teo. Create a file named schema.teo. Specify which database to connect and which port to listen.

connector {
  provider: .sqlite,
  url: "sqlite::memory:"
}
 
server {
  bind: ("0.0.0.0", 5050)
}
 
model User {
  @id @autoIncrement @readonly
  id: Int
  @unique @onSet($if($presents, $isEmail))
  email: String
  name: String?
  @relation(fields: .id, references: .authorId)
  posts: Post[]
}
 
model Post {
  @id @autoIncrement @readonly
  id: Int
  title: String
  content: String?
  @default(false)
  published: Bool
  @foreignKey
  authorId: Int
  @relation(fields: .authorId, references: .id)
  author: User
}

Start the server with teo serve command. Now you can create, update, delete, read, aggregate and group by. Read our Query client guide for detailed usage.

Write custom handlers

Declare the handler in the schema.

@map(.get, "/echo/:data", interface: "EchoCaptures")
declare nonapi handler echo(): Any

Implement the handler with program code.

Node.js implementation

import { App, Response, Request } from '@teodevgroup/teo'
import { EchoCaptures } from './entities'
 
const app = new App()
app.mainNamespace().defineHandler("echo", (request: Request) => {
    const captures: EchoCaptures = request.captures()
    return Response.string(captures.data, "text/plain")
})
app.run()

Python implementation

from asyncio import run
from teo import App, Response, Request
from entities import EchoCaptures
 
async def main():
    app = App()
    def echo_handler(request: Request):
        captures: EchoCaptures = request.captures()
        return Response.string(captures["data"], "text/plain")
    app.main_namespace.define_handler("echo", echo_handler)
    await app.run()
 
run(main())

Rust implementation

mod entities;

use tokio::main;
use teo::prelude::{App, Response, Result, path};
use crate::entities::EchoCaptures;

#[main]
async fn main() -> Result<()> {
    let app = App::new()?;
    app.main_namespace().define_handler("echo", |captures: EchoCaptures| async move {
        Ok::<Response, Error>(Response::string(captures.data(), "text/plain"))
    });
    app.run().await
}

Tutorials

We prepared a Beginner tutorial series to help you learn and understand Teo.

Issues

Welcome to submit issues in this repo.

Contributing

Read our Contributing guide to set projects up and start contributing.

License

TEO is under Apache 2.0 license.