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