Total.js v5: Schemas and Actions.
If you’re diving into Total.js development, you’ve chosen a robust, modern framework that’s packed with powerful features for building fast, scalable applications. At the heart of Total.js are two essential concepts that will guide much of your backend logic: schemas and actions.
Schemas and actions might seem complex at first, but once you understand how they work together, they’ll become some of your favorite tools in the framework. In this guide, I’ll break down these concepts, show you
how to set them up, and walk you through practical examples that will empower you to create an organized, flexible codebase.
Let's get started!
Understanding schemas and actions in Total.js
In Total.js, schemas and actions play distinct roles that complement each other:
Schemas: These are blueprints for organizing data and the operations that manage it. With schemas, you define the structure of your data and associate it with specific actions that can perform tasks on it, such as creating, updating, or deleting records.
Actions: Actions in Total.js represent business logic for performing specific tasks. Actions can be tied to schemas (schema actions) or created as standalone functions that handle tasks not directly linked to any schema.
Think of schemas as structured “folders” where you organize your data logic, while actions are the “tools” that operate on that data. You’ll be able to call actions as needed, whether they belong to a schema or stand alone, and they’re especially useful for handling backend operations like processing user input or interacting with a database.
Getting Started with Schemas in Total.js
1. Setting Up a Basic Schema
A schema in Total.js is more than just a data structure. It’s a powerful way to group related actions that handle specific tasks for a particular type of data. Here’s a simple example of creating a schema for Users
.
In your total.js application create a folder schemas
and then create a file users.js
inside to paste the following:
NEWSCHEMA('Users', function(schema) {
// Action: list
schema.action('list', {
name: 'Listing operation',
query: '*search:String', // Query parameters
action: function($) {
// Action logic goes here
$.success(); // Send a success response
}
});
// Action: insert
schema.action('insert', {
name: 'Creation operation',
input: '*name:String, *email:Email', // Input validation
action: function($, model) {
// Action logic for inserting user
$.success(model); // Respond with the inserted model data
}
});
// Action: read
schema.action('read', {
name: 'Reading operation',
params: '*id:UID', // Parameter validation
action: function($) {
// Action logic to read a user by ID
$.success(); // Send a success response
}
});
});
In this example, we created a schema called Users
with three actions:
- list: Returns a list of users based on search parameters.
-
insert: Adds a new user to the database with validation for required fields (
name
andemail
). - read: Retrieves a specific user by their unique ID.
By organizing these actions within the Users
schema, you create a cohesive set of operations for handling user data.
2. Linking Schemas to Routes
To make these schema actions accessible via HTTP requests, you can link them to routes in Total.js. This will allow your frontend or API clients to call these actions. Just create a controller file controllers/api.js
to put the following:
exports.install = function () {
ROUTE('GET /api/users/ --> Users/list');
ROUTE('POST /api/users/insert --> Users/insert');
ROUTE('GET /api/users/{id} --> Users/read');
}
In this example:
- A
GET
request to/api/users/
will call thelist
action. - A
POST
request to/api/users/insert
will invoke theinsert
action. - A
GET
request to/api/users/{id}/
will trigger theread
action with a unique user ID passed in the URL.
This structure keeps your routing and backend logic organized and straightforward.
Standalone actions
While schema actions are great for data-centric tasks, sometimes you’ll need an action that performs a standalone operation, not linked to a specific schema. Standalone actions are defined independently and can be used for any custom backend functionality.
1. Creating a Standalone Action
Total.js recommand to create your actions file in actions
folder. But you can put them somewhere else like (schemas,definitions,modules,etc
)
Let’s say we want to create a standalone action called find
. This action accepts query parameters for pagination and sorting without being tied to a schema.
Let us create this file in actions/default.js
and copy/paste the following:
NEWACTION('find', {
query: 'page:Number,sort:String',
params: 'projectid:String',
action: function($) {
// Logic to find specific data based on query and params
$.success(); // Send a success response
}
});
This find
action can be called to handle any general-purpose data search, making it a flexible solution for various backend needs.
2. Connecting standalone actions to routes
Just like schema actions, standalone actions need to be linked to routes to be accessed from your API or frontend.
ROUTE('GET /api/find/ --> find');
With this route, a GET
request to /api/find/
will call the standalone find
action.
Using ACTION()
Total.js provides the ACTION()
method, a way to call both schema-related and standalone actions in your code.
Example
Let’s call the Users/insert
action we created earlier using ACTION()
:
ACTION('Users/insert', { name: 'John', email: 'johndoe@gmail.com' }).callback(function(err, response) {
if (err) {
console.error('Action error:', err);
} else {
console.log('User insert response:', response);
}
});
Here, we specify the Users/insert
action and pass a search query to find users with “John” in their data. You can use this approach to call any schema or standalone action, making ACTION()
a highly flexible tool.
Advanced: Calling Schema Actions Within Other Schema Actions
Total.js allows you to call actions within the same schema using the $.action
method. This feature is powerful for creating complex workflows that involve multiple steps.
Example: Nested Schema Actions
Let’s say we want an action in the Users
schema to first list users, then perform additional processing based on that list.
NEWSCHEMA('Users', function(schema) {
schema.action('list', {
name: 'Listing users',
query: 'search:String',
action: function($) {
$.success([{ name: 'John Doe' }, { name: 'Jane Doe' }]); // Sample data
}
});
schema.action('proccess', {
action: async function($) {
// Call the list action within the same schema
$.action('list').callback(function(err, users) {
if (err) return $.invalid(err);
// Process users after retrieving the list
users.forEach(user => {
console.log('Processing user:', user.name);
});
$.success('Users processed successfully!');
});
// or
// var response = await $.action('list').query({ search: 'totaljs' }).user($.user).promise($);
}
});
});
In this example, proccess
calls list
within the Users
schema. This structure is great for chaining operations within schemas and gives you full control over workflow management.
Advanced usage
Total.js v5 allows so many other usages of NEWSCHEMA
and NEWACTION
for very specific cases. We are not going to cover them here because we are preparing another blog post for them. But if you are curious about learning them you can check this blog post
Key Takeaways and Tips
Working with schemas and actions in Total.js can elevate your application’s structure and efficiency. Here are some key points to keep in mind:
- Schemas are collections of related actions tied to specific data entities. Use them to organize and validate your data-centric actions.
- Standalone actions allow you to build independent functions for tasks that don’t fit within a schema.
- Use
ACTION()
for flexible action calls, whether they’re schema-based or standalone. - Route linking connects your actions to HTTP endpoints, making your backend logic accessible via API routes.
- For more complex workflows, nested actions within schemas give you a streamlined way to manage multi-step processes.
With these foundations in place, you’re ready to start building robust, modular backend logic in Total.js! Experiment with different schema and action configurations, and don’t hesitate to explore Total.js’s extensive documentation as you continue to master this flexible framework.
Happy coding!
Top comments (0)