This documentation describes the use of the basic API modules `SearchApi` and `SaveApi`, designed for rapid development of RESTful API endpoints. These modules allow you to create, read, update, and delete (CRUD) data with a minimal amount of code, providing flexible mechanisms for validation, filtering, and data transformation.
namespace App.Database;
use Runtime.BaseObject;
use Runtime.ORM.Record;
use Runtime.ORM.Annotations.AutoIncrement;
use Runtime.ORM.Annotations.BigIntType;
use Runtime.ORM.Annotations.Primary;
use Runtime.ORM.Annotations.StringType;
class Item extends Record
{
/**
* Returns table name
*/
pure string getTableName() => "forms";
/**
* Returns table schema
*/
pure memorize Collection<BaseObject> schema() =>
[
/* Fields */
new BigIntType{"name": "id"},
new StringType{"name": "name"},
new StringType{"name": "description"},
new BigIntType{"name": "category_id"},
new DateTimeType{"name": "gmtime_add", "autocreate": true},
new DateTimeType{"name": "gmtime_edit", "autoupdate": true},
/* Index */
new AutoIncrement{"name": "id"},
new Primary{"keys": ["id"]},
];
}The `SearchApi` module provides basic functionality for creating API endpoints designed for searching and retrieving data from a database. It is developed for flexible query configuration and result processing.
Key Features
namespace App.Admin.Api;
use Runtime.Serializer.MapType;
use Runtime.ORM.Query;
use Runtime.Web.Annotations.ApiMethod;
use Runtime.Widget.Api.SearchApi;
use Runtime.WordPress.Admin.AdminMiddleware;
use App.Database.Item;
class ItemSearchApi extends SearchApi
{
/**
* Returns api name
*/
pure string getApiName() => "admin.item";
/**
* Returns record name
*/
pure string getRecordName() => classof Item;
/**
* Returns middleware
*/
Vector<Middleware> getMiddleware() =>
[
new AdminMiddleware(),
];
/**
* Returns data rules
*/
void getDataRules(MapType rules)
{
}
/**
* Returns item fields
*/
Vector<string> getItemFields() =>
[
"id",
"name"
];
/**
* Build Query
*/
async void buildQuery(Query q)
{
}
/**
* Action search
*/
@ApiMethod{ "name": "search" }
async void actionSearch()
{
await parent();
}
/**
* Action item
*/
@ApiMethod{ "name": "item" }
async void actionItem()
{
await parent();
}
}The `SaveApi` module provides basic functionality for creating API endpoints designed for saving (creating and updating) and deleting data in a database. It ensures robust data validation, handles CRUD operations, and offers flexible logic configuration through a hook system.
Key Features
Two main actions:
Continuing the example with the `Item` entity, to create an API for saving and deleting items, we can define the following class:
namespace App.Api;
use Runtime.Widget.Api.SaveApi;
use Runtime.Widget.Api.Rules.UniqueRules;
use Runtime.WordPress.Admin.AdminMiddleware;
use App.Database.Item;
class ItemSaveApi extends SaveApi
{
/**
* Returns api name
*/
pure string getApiName() => "app.item";
/**
* Returns record name
*/
pure string getRecordName() => classof Item;
/**
* Returns middleware
*/
Vector<Middleware> getMiddleware() =>
[
new AdminMiddleware(),
];
/**
* Returns save rules
*/
Vector<BaseRule> rules() =>
[
new UniqueRules{"field_name": "name"},
];
/**
* Returns data rules
*/
void getDataRules(MapType rules)
{
}
/**
* Returns item rules
*/
void getItemRules(MapType rules)
{
rules.addType("id", new IntegerType());
rules.addType("name", new Required());
rules.addType("name", new StringType());
rules.addType("description", new StringType());
rules.addType("category_id", new IntegerType());
}
/**
* Returns item fields
*/
Vector<string> getItemFields() =>
[
"id",
"name",
"description",
"category_id",
"gmtime_add",
"gmtime_edit",
];
/**
* Build query
*/
async void buildQuery(Query q)
{
await parent(q);
if (this.foreign_key && this.foreign_key.has("category_id"))
{
q.where("category_id", "=", this.foreign_key.get("category_id"));
}
}
/**
* Save before
*/
async void onSaveBefore()
{
await parent();
}
/**
* Save after
*/
async void onSaveAfter()
{
await parent();
}
/**
* Delete before
*/
async void onDeleteBefore()
{
await parent();
/* Check if has orders */
if (this.item.get("has_orders"))
{
throw new ApiError(new RuntimeException(
"Cannot delete record because there are related orders."
));
}
}
/**
* Delete after
*/
async void onDeleteAfter()
{
}
/**
* Save action
*/
@ApiMethod{ "name": "save" }
async void actionSave()
{
await parent();
}
/**
* Delete action
*/
@ApiMethod{ "name": "delete" }
async void actionDelete()
{
await parent();
}
}