AgapeToolkit is a collection of TypeScript libraries for building modern APIs and UIs with clarity, consistency, and confidence.
It provides a single source of truth for your data models and powers validation, serialization, ORM, API layers, and user interfaces — all from the same definitions.
Status: Active development. Expect rapid iteration and breaking changes until v1.0.
This monorepo contains multiple packages published under the @agape/* scope. Each can be used independently or together.
| Package | Description | npm | Docs |
|---|---|---|---|
@agape/model |
Annotate and validate models for APIs and UIs. | Docs | |
@agape/api |
Build REST APIs directly from your models. | Docs | |
@agape/orm |
Simple ORM for mapping models to relational databases. | Docs | |
@agape/ui |
Render forms, tables, and other UI components using models. | Docs | |
@agape/alchemy |
Serialization and deserialization utilities for models. | Docs | |
@agape/object |
Compose classes with mixin-style traits and behavioral decorators. | Docs |
These packages are used internally by the main libraries but can also be useful on their own.
| Package | Description | npm | Docs |
|---|---|---|---|
@agape/datetime |
Format and parse dates using Unicode patterns and Intl.DateTimeFormat. | Docs | |
@agape/locale |
Serialization and deserialization utilities for models. | Docs | |
@agape/metadata |
Annotate and validate models for APIs and UIs. | Docs | |
@agape/string |
Build REST APIs directly from your models. | Docs | |
@agape/temporal |
Temporal API polyfill with graceful fallback for unsupported environments. | Docs | |
@agape/types |
Simple ORM for mapping models to relational databases. | Docs | |
@agape/util |
Utility functions for object manipulation and validation. | Docs |
See agape.dev for the full list of packages and documentation.
Let's build a complete application for editing employee records.
import { Model, Field } from '@agape/model';
@Model
class Employee {
@Field
@PrimaryKey
id!: number;
@Field
@Alphanumeric
number!: string;
@Field
@MaxLength(64)
name!: string;
@Field
@Email
email!: string;
}import { orm } from '@agape/orm';
orm.register(Employee);import { Controller } from '@agape/api';
import { Traits } from '@agape/object';
interface EmployeeController extends HasCrudOperations<Employee> { }
@Controller('employees')
@Traits(CanPerformCrud(Employee))
class EmployeeController { }import express from 'express';
import { bootstrapExpress } from '@agape/api';
const app = express();
boostrapExpress(app, EmployeeController);
app.listen(3000);ag g client --name EmployeeApi \
--server http://localhost:3000 \
--root /api
--controller EmployeeController
--models @myapp/models
--output apps/frontend/src/app/shared/services/employee-api.tsimport { Route } from '@angular/router';
import { crudRoutes } from '@agape/ui';
import { EmployeeApi } from './shared/services/employee-api';
export const appRoutes: Route[] = [
...crudRoutes(
{
path: '/employees',
model: Employee,
api: EmployeeApi
}
)
];Contributions are welcome! Please see CONTRIBUTING.md for details.
MIT © 2025 Maverik Minett