PartialSchema is a type that represents a Hatchify schema. This document describes the relationship between names in the schema and the resulting names used in the database, service APIs, and UI. We will first review the general guidelines and then how specific parts in the schema relate to names in the database, service API, and UI.
- General Guidelines
- Schema
Hatchify attempts to adhere to the most common naming pattern conventions. The following are the casing and pluralization guidelines that Hatchify uses.
By default, Hatchify uses PascalCase (Ex: SalesPerson) for type names and uses camelCase names for member names (Ex: firstName). The following are the exceptions:
- Tables and table column names use snake_case (Ex:
sales_persontable andfirst_namefield). - Service URL path names are kebab-case. (Ex:
/sales-people) Note: Query parameters are camelCase.
Hatchify simply adds an "s" to make values names plural. We will show how to customize this below.
The following are singular:
- Schema model names (Ex:
SalesPerson) - Table names (Ex:
sales_person) belongsTorelationship names (Ex:manager: belongsTo("SalesPerson"))
The following are plural:
- Service URL path names (Ex:
/sales-persons) hasManyrelationship names (Ex:managers: hasMany("SalesPerson"))
The schema name should be singular PascalCase as follows:
const SalesPerson = {
name: "SalesPerson", // 👀
attributes: {
firstName: string(),
},
} satisfies PartialSchemaCreates a sales_person table.
Querying Data
Creates a /sales-persons API.
SalesPerson will be used in the fields query parameter:
GET /api/sales-persons?fields[SalesPerson]=nameData Response
SalesPerson will be used as the response type:
{
"data": {
"type": "SalesPerson" // 👀
...
}
}Unless displayName is specified, the name value is used for:
- column headers
- form labels
Optionally set the pluralName to configure plural naming for a schema.
const SalesPerson = {
name: "SalesPerson",
pluralName: "SalesPeople", // 👀
attributes: {
firstName: string(),
},
} satisfies PartialSchemaQuerying Data
Creates a /sales-people API.
name will still be used in the fields query parameter:
GET /api/sales-persons?fields[SalesPerson]=nameData Response
name will still be used as the response type:
{
"data": {
"type": "SalesPerson"
...
}
}Optionally set tableName to control the name of the database table for the schema.
const SalesPerson = {
name: "SalesPerson",
tableName: "acme_sales_people", // 👀
attributes: {
firstName: string(),
},
} satisfies PartialSchema- Creates a table
acme_sales_people.
Optionally set readOnly to create only GET middleware for this schema. This is useful when data is populated from somewhere else or when pointing the schema to a SQL view.
const SalesPerson = {
name: "SalesPerson",
readOnly: true, // 👀
attributes: {
firstName: string(),
},
} satisfies PartialSchema- Prevent creation of the create/update/delete middleware.
Optionally set namespace when using Postgres to use Postgres Schemas which are like namespaces for tables. The namespace must be written as singular PascalCase as follows:
const AcmeCorp_SalesPerson = {
name: "SalesPerson",
namespace: "AcmeCorp", // 👀
attributes: {
firstName: string(),
},
} satisfies PartialSchemaCreates a table sales_person in the Postgres schema acme_corp.
Querying Data
Creates an acme-corp/sales-persons API.
namespace_name, will be used in the fields query parameter:
GET /api/acme-corp/sales-persons?fields[AcmeCorp_SalesPerson]=nameData Response
namespace_name will be used as the response type:
{
"data": {
"type": "AcmeCorp_SalesPerson", // 👀
"id": "f06f81f2-4bea-4a60-99ad-8da8ecf79473",
...
}
}hatchifyKoa({AcmeCorp_SalesPerson}) returns models.AcmeCorp_SalesPerson
hatchifyReact({AcmeCorp_SalesPerson}) returns [components|model|state].AcmeCorp_SalesPerson
JSON:API requires that the id attribute be named id, therefore this attribute cannot be renamed.
Customizing the id attribute is as simple as adding an attribute:
const SalesPerson = {
name: "SalesPerson",
id: integer({ autoIncrement: true }), // 👀
attributes: {
firstName: string(),
},
} satisfies PartialSchemaOptionally set the displayAttribute to configure which attribute is used to display a relationship in the UI. If the displayAttribute is not set, then the first attribute will be used.
const SalesPerson = {
name: "SalesPerson",
ui: { displayAttribute: "email" }, // 👀
attributes: {
name: string(),
email: string(),
},
relationships: {
accounts: hasMany("Account"),
},
} satisfies PartialSchema
const Account = {
name: "Account",
attributes: {
name: string(),
},
relationships: {
salesPerson: belongsTo("SalesPerson"),
},
} satisfies PartialSchemaWhen displaying an Account table in the UI, the email attribute will be used in the "Sales Person" column. If displayAttribute was not set, then the name attribute would have been used.
Naming for attributes
Naming for relationships: