Conversions
trim, trimStart, trimEnd, toLowerCase and toUpperCase, default values or default functions, and conversionFun to compute a value, like a slug from a name.
API Maker
The framework for AI era
Database APIs
Describe a table once. Every write through the schema APIs is converted and checked for you.
The schema of a table is a TypeScript object: the type of each field, how to clean it, its default, its rules and its relations. API Maker detects a first version from your data. From then on, the schema APIs trim, convert, validate, encrypt and number your data before it reaches the database.
From the columns of a SQL table, or from the first 100 documents of a MongoDB collection. Edit it to add your rules.
Values are converted to the field type, trimmed or cased, filled with defaults, and passed through your own conversion function.
required, min, max, minLength, maxLength, email, enum and your own validator function run on every save and update.
Ids are generated or incremented by API Maker when the request has none.
The API answers 400 with one error per problem, with the field and the rule it broke.
trim, trimStart, trimEnd, toLowerCase and toUpperCase, default values or default functions, and conversionFun to compute a value, like a slug from a name.
required, min, max, minLength, maxLength, email and enum, plus validatorFun for rules that need the whole object.
A SUPER_KEY validation keeps a group of fields unique together, like a slug inside a category, with your own error message.
isAutoIncrementByAM counts from your start value with your step. isAutoGenerateByAM creates a UUID, ObjectID, ULID or short UUID.
encryption stores a field encrypted with the key of your secret (AES, RC4 or TripleDES); decrypt it with g.sys.system.decrypt when you need it. hashing stores a one-way HMAC SHA-256 hash.
Mark a version field with isConcurrencyControlField: an update carrying an old version fails instead of overwriting someone else's change.
A web app, a mobile app and a partner integration all save products. The rules live in the schema, so each of them gets the same checks, the same defaults and the same error messages, and none of them can store a product without a category.
import { EType, ISchemaType, ISchemaProperty } from 'types';import * as T from 'types';const schema: ISchemaType = { _id: <ISchemaProperty>{ __type: EType.objectId, isPrimaryKey: true, isAutoGenerateByAM: { valueGeneratorType: 'ObjectID' } }, product_no: <ISchemaProperty>{ __type: EType.number, isAutoIncrementByAM: { start: 1000, step: 1 } }, name: <ISchemaProperty>{ __type: EType.string, validations: { required: true, minLength: 2, maxLength: 120 }, conversions: { trim: true } }, status: <ISchemaProperty>{ __type: EType.string, validations: { enum: ['DRAFT', 'ACTIVE', 'ARCHIVED'] }, conversions: { toUpperCase: true, defaults: { defaultValue: 'DRAFT' } } }, category: <ISchemaProperty>{ __type: EType.objectId, validations: { required: true }, database: 'shop', collection: 'categories', column: '_id' }, slug: <ISchemaProperty>{ __type: EType.string }, supplier_tax_id: <ISchemaProperty>{ __type: EType.string, conversions: { encryption: true } }, version: <ISchemaProperty>{ __type: EType.number, isConcurrencyControlField: true },};const validations: T.IDataValidation[] = [{ name: 'unique_slug_per_category', paths: ['category', 'slug'], type: T.EDataValidationType.SUPER_KEY, errorMessage: 'That slug already exists in this category.',}];module.exports = { schema, validations };{ "success": false, "statusCode": 400, "errors": [ { "type": "required", "field": "category", "code": 400, "message": "Please provide valid 'category' field with type 'objectId'." }, { "type": "enumValidation", "field": "status", "code": 400, "message": "Property 'status' should have any value from [DRAFT, ACTIVE, ARCHIVED]." } ]}Messages come from the language pack of the caller, in the language it asks for.
Yes. The system API is-valid-data-for-table (g.sys.system.isValidDataForTable) runs the same conversions and validations and returns the errors.
The schema APIs refuse it with a schemaKeyNotFound error, "Property not found in schema for key …", instead of storing it.
Yes. instance, database, collection or table, and column on a field point to another table. Deep populate, find and join and master save follow them, even into another database.
Not by default: calls from custom code skip it. Pass skipConcurrencyControl: false to use it there too.