Skip to content

Latest commit

 

History

History
131 lines (102 loc) · 5.26 KB

1.introduction.md

File metadata and controls

131 lines (102 loc) · 5.26 KB
title Expose database records through an API
description Build a first data controller that serves CRUD routes for a users table, then check which fields it reads and writes.
mode tutorial

Overview

In this tutorial, we expose a users table through five CRUD routes with @antelopejs/interface-data-api. A data controller connects the table model to HTTP handlers. Its metadata decides which fields clients can read, write, list and filter.

Build one resource first

We build one resource in four steps.

  1. Prepare the database. Define a table and register its schema with database-decorators. The AntelopeJS project needs a database module and an API module.
  2. Choose the routes. Start with the route set your clients need, instead of exposing every write route by default.
  3. Set the field policy. Add access rights, validators and list fields. Field permissions do not authenticate users and do not authorize access to rows.
  4. Check one read and one rejected write. Confirm that the response leaves out private fields and that invalid input never reaches storage. Then add relationships and filters.

Quick start

The example declares all five CRUD routes for a users table. It assumes a configured database module and an existing my-database instance. Import the table declaration, then await RegisterSchema("myapp") when the declaring module initializes. Wait for that setup to finish before the module serves requests.

This example sets a field policy. It is not a production account system. AccessMode.WriteOnly keeps the password out of responses, but it does not hash the password or authenticate requests. Add a database modifier and your authentication policy before you accept real credentials.

import { Controller } from "@antelopejs/interface-api";
import {
  DataController,
  DefaultRoutes,
  RegisterDataController,
} from "@antelopejs/interface-data-api";
import {
  Access,
  AccessMode,
  Listable,
  Mandatory,
  ModelReference,
} from "@antelopejs/interface-data-api/metadata";
import {
  BasicDataModel,
  Field,
  Index,
  Model,
  RegisterTable,
  Table,
} from "@antelopejs/interface-database-decorators";

@RegisterTable("users", "myapp")
class User extends Table {
  @Field("string")
  declare _id: string;

  @Index()
  @Field("string")
  declare email: string;

  @Field("string")
  declare name: string;

  @Field("string")
  declare password: string;
}

class UserModel extends BasicDataModel(User, "users") {}

@RegisterDataController()
class UserAPI extends DataController(
  User,
  DefaultRoutes.All,
  Controller("/users"),
) {
  @ModelReference()
  @Model(UserModel, "my-database")
  declare userModel: UserModel;

  @Listable()
  @Access(AccessMode.ReadOnly)
  declare _id: string;

  @Listable()
  @Access(AccessMode.ReadWrite)
  @Mandatory("new", "edit")
  declare email: string;

  @Listable()
  @Access(AccessMode.ReadWrite)
  @Mandatory("new")
  declare name: string;

  @Access(AccessMode.WriteOnly)
  @Mandatory("new")
  declare password: string;
}

The controller serves these REST endpoints.

Method Endpoint Description
GET /users/get?id=<id> Read one user
GET /users/list?limit=10 List users, one page
POST /users/new Create a user
PUT /users/edit?id=<id> Update a user
DELETE /users/delete?id=<id> Delete a user

Check the field policy

Use disposable data and the base URL of your API module. First, create a user with POST /users/new and a body that holds name, email and a dummy password. The response is the created user, with its _id and without password. Use that _id in the next checks.

  1. GET /users/get?id=<id> returns the readable fields. You see _id, email and name, and never password.
  2. GET /users/list?limit=10 returns _id, name and email for each entry of results.
  3. PUT /users/edit?id=<id> with { "name": "Updated" } keeps the email you did not send. With { "email": "" }, the route answers 400, because email is mandatory on edit.

@Mandatory does not check the email syntax or the password strength. Add validators before you accept untrusted input.

Core guides

Relationships and advanced queries

  • Foreign keys. Relations between tables.
  • Filters. Filters on list endpoints.
  • Modifiers. Data transformation with database-decorators modifiers.
  • Joined fields. A remote field flattened onto each row, sortable and filterable in the database.
  • Computed fields. Values computed in the database, sortable and pageable there.