Atom
is the most basic element of CabloyJS, such as article
, announcement
, leave application
, etc.
Through the combination of Atom
, we can achieve any desired requirements, such as CMS
, OA
, CRM
, ERP
and so on.
It is precisely because a general concept of Atom
has been abstracted from various business models
, that CabloyJS realizes many common features and functions for Atom
, thus enabling various practical business conveniently
For more detailed concepts of Atom
, see: Cabloy: Basic Concepts of Atom
Here, the basic concepts and usage are introduced mainly through the atomClass party
Business Module Template: module-business
If business logics to be developed, it is recommended that the business module template module-business
be used to create the file skeleton of the business module
. This template automatically creates business-related code, greatly simplifying the workload
$ cd /path/to/project
$ npm init cabloy src/module/test-party --type=module-business
Declaration of AtomClass
AtomClass
is the metadata information corresponding to Atom
, which is also set in meta
of the module
src/module/test-party/backend/src/meta.js
const meta = {
base: {
atoms: {
party: {
info: {
title: 'Party',
tableName: 'testPartyView',
flow: 0,
},
actions: {
},
flags: {
},
validator: 'party',
search: {
validator: 'partySearch',
},
},
},
},
};
Name | Description |
---|---|
info.title | AtomClass’s title |
info.tableName | The name of the data table or view |
info.flow | Whether to enable simple flow |
validator | used to render form and validate form data |
search.validator | used to render custom search form fields |
Data Table
All code related to module data architecture
change is in the backend API route version/update
, which facilitates the maintenance of module data version
, thus achieving seamless upgrade of module
src/module/test-party/backend/src/service/version.js
async update(options) {
if (options.version === 1) {
// create table: testParty
let sql = `
CREATE TABLE testParty (
id int(11) NOT NULL AUTO_INCREMENT,
createdAt timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
updatedAt timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted int(11) DEFAULT '0',
iid int(11) DEFAULT '0',
atomId int(11) DEFAULT '0',
personCount int(11) DEFAULT '0',
partyTypeId int(11) DEFAULT '0',
PRIMARY KEY (id)
)
`;
await this.ctx.model.query(sql);
}
}
Model
Defining model objects corresponding to data tables makes it easier to manipulate data
src/module/test-party/backend/src/model/party.js
module.exports = app => {
class Party extends app.meta.Model {
constructor(ctx) {
super(ctx, { table: 'testParty', options: { disableDeleted: false } });
}
}
return Party;
};
Name | Default | Description |
---|---|---|
table | The name of the data table or view corresponding to the model object | |
disableDeleted | false | Disable Soft Deletion feature |
Form Validation
CabloyJS’s Form Validation
mechanism uses ajv
. Suggest you have a preliminary understanding of ajv
With the Form Validation
, we can automatically render the form by defining the business-related JSON Schema
, and validate the form data automatically. If the form data does not meet expectations, the error messages will be displayed automatically
For more information about Form Validation
, see: Cabloy: Form Validation
src/module/test-party/backend/src/config/validation/schemas.js
module.exports = app => {
const schemas = {};
// party
schemas.party = {
type: 'object',
properties: {
atomName: {
type: 'string',
ebType: 'text',
ebTitle: 'Party Name',
notEmpty: true,
},
personCount: {
type: 'number',
ebType: 'text',
ebTitle: 'Person Count',
notEmpty: true,
},
partyTypeId: {
type: 'number',
ebType: 'select',
ebTitle: 'Party Type',
ebOptionsUrl: '/test/party/party/types',
ebOptionTitleKey: 'name',
ebOptionValueKey: 'id',
ebOptionsBlankAuto: true,
notEmpty: true,
},
},
};
// party search
schemas.partySearch = {
type: 'object',
properties: {
partyTypeId: {
type: 'number',
ebType: 'select',
ebTitle: 'Party Type',
ebOptionsUrl: '/test/party/party/types',
ebOptionTitleKey: 'name',
ebOptionValueKey: 'id',
ebOptionsBlankAuto: true,
},
},
};
return schemas;
};
Atom Action
& API Route
CabloyJS refers to all operations of business data as Atom Action
, which fall into two main categories:
Basic Action
: create、read、write、deleteCustom Action
:business-specific operations, such asreview
,publish
, etc.
CabloyJS provides a set of basic API routes
, encapsulates atom actions
, so that middlewares such as database transaction
, validator',
right` can be configured uniformly
Business module
only need to provide business API routes
, which will be called by basic API routes
when appropriate
Business API Routes
src/module/test-party/backend/src/routes.js
// party
// atom: party
{ method: 'post', path: 'party/create', controller: party, middlewares: 'inner', meta: { auth: { enable: false } } },
{ method: 'post', path: 'party/read', controller: party, middlewares: 'inner', meta: { auth: { enable: false } } },
{ method: 'post', path: 'party/select', controller: party, middlewares: 'inner', meta: { auth: { enable: false } } },
{ method: 'post', path: 'party/write', controller: party, middlewares: 'inner,validate',
meta: {
auth: { enable: false },
validate: { validator: 'party', data: 'item' },
},
},
{ method: 'post', path: 'party/delete', controller: party, middlewares: 'inner', meta: { auth: { enable: false } } },
{ method: 'post', path: 'party/action', controller: party, middlewares: 'inner', meta: { auth: { enable: false } } },
{ method: 'post', path: 'party/enable', controller: party, middlewares: 'inner', meta: { auth: { enable: false } } },
Name | Description |
---|---|
middlewares: ‘inner’ | middleware inner , indicates this API route only be allowed inner access |
middlewares: ‘auth’ | Since the basic API routes will pass in the object user when calling the business API routes , the global middleware auth is disabled here to reduce unnecessary operations |
party/create | create an item of party |
party/read | select single item of party |
party/select | select some items of party |
party/write | update an item of party |
party/delete | delete an item of party |
party/action | custom actions of party |
party/enable | change status of party from draft to normal |
Business Logic Codes
src/module/test-party/backend/src/service/party.js
module.exports = app => {
class Party extends app.Service {
async create({ atomClass, key, item, user }) {
// add party
const res = await this.ctx.model.party.insert({
atomId: key.atomId,
});
// return key
return { atomId: key.atomId, itemId: res.insertId };
}
async read({ atomClass, key, item, user }) {
// read
}
async select({ atomClass, options, items, user }) {
// select
}
async write({ atomClass, key, item, validation, user }) {
// update party
await this.ctx.model.party.update({
id: key.itemId,
personCount: item.personCount,
partyTypeId: item.partyTypeId,
});
}
async delete({ atomClass, key, user }) {
// delete party
await this.ctx.model.party.delete({
id: key.itemId,
});
}
async action({ action, atomClass, key, user }) {
}
async enable({ atomClass, key, atom, user }) {
}
}
return Party;
};
Comments: