CabloyJS refers to all operations of business data as Atom Action, which fall into two main categories:

  1. Basic Action: create、read、write、delete
  2. Custom Action:business-specific operations, such as review, publish, etc.

CabloyJS provides a set of basic API routes, encapsulates atom actions, so that middleware 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

Basic Actions

Definition

Module a-base provides the generic logic of basic actions, which is defined as follows:

a-base/backend/src/config/constants.js

atom: {
  action: {
    create: 1,
    read: 2,
    write: 3,
    delete: 4,
    save: 51,
    submit: 52,
    custom: 100, // custom action start from custom
  },
  actionMeta: {
    create: { title: 'Create', actionComponent: 'action' },
    read: { title: 'View', actionPath: 'atom/view?atomId={{atomId}}&itemId={{itemId}}&atomClassId={{atomClassId}}&module={{module}}&atomClassName={{atomClassName}}&atomClassIdParent={{atomClassIdParent}}' },
    write: { title: 'Edit', actionPath: 'atom/edit?atomId={{atomId}}&itemId={{itemId}}&atomClassId={{atomClassId}}&module={{module}}&atomClassName={{atomClassName}}&atomClassIdParent={{atomClassIdParent}}' },
    delete: { title: 'Delete', actionComponent: 'action' },
    save: { title: 'Save', actionComponent: 'action', authorize: false },
    submit: { title: 'Submit', actionComponent: 'action', authorize: false },
    custom: { title: 'Custom' },
  },
},
Name Description
title action’s title
actionModule The module name of the frontend component, which is the current module by default
actionComponent frontend component
actionPath frontend page component route
authorize Whether a separate authorization is required. Because save and submit are auxiliary actions of write, no separate authorization is required
custom action placeholder, custom actions start from 101

The general logic of basic actions provided by module a-base can meet the needs of most scenarios. If you want to customize the logic of basic actions, you only need to provide a combination of actionModule, actionComponent and actionPath

Basic API Route

Module a-base provides a set of basic API routes, so that middlewares such as database transaction, validator',right` can be configured uniformly

a-base/backend/src/routes.js

{ method: 'post', path: 'atom/create', controller: atom, middlewares: 'transaction',
  meta: { right: { type: 'atom', action: 1 } },
},
{ method: 'post', path: 'atom/read', controller: atom,
  meta: { right: { type: 'atom', action: 2 } },
},
{ method: 'post', path: 'atom/select', controller: atom },
{ method: 'post', path: 'atom/write', controller: atom, middlewares: 'transaction',
  meta: { right: { type: 'atom', action: 3 } },
},
{ method: 'post', path: 'atom/submit', controller: atom, middlewares: 'transaction',
  meta: { right: { type: 'atom', action: 3 } },
},
{ method: 'post', path: 'atom/delete', controller: atom, middlewares: 'transaction',
  meta: { right: { type: 'atom', action: 4 } },
},

Business API Route

Business module only need to provide business API routes, which will be called by basic API routes when appropriate

For example, the business API routes of module test-party is as follows:

modules/test-party/backend/src/routes.js

{ 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 } } },

Why disable the global middleware auth?

  • Since the basic API rotues will pass in the object user when performing the business API routes, the global middleware auth is disabled here to reduce unnecessary operations

Business Logic Codes

create

The business logic of action create generally performs the following operations:

  1. Create a new item of business table
  2. Initialize fields of atom (optional)
  3. Return atom key

src/module/test-party/backend/src/service/party.js

async create({ atomClass, key, item, user }) {
  // add party
  const res = await this.ctx.model.party.insert({
    atomId: key.atomId,
  });
  return { atomId: key.atomId, itemId: res.insertId };
}

read

Generally, it is not necessary to add business logic codes for action read, because the object item has retrieved the data of table aAtom and business table

If you want to attach data other than the table aAtom and business table, you can directly operate the object item here

src/module/test-party/backend/src/service/party.js

async read({ atomClass, key, item, user }) {
  // read
  this._getMeta(item);
}

select

Generally, it is not necessary to add business logic codes for action select, because the object items has retrieved the data of table aAtom and business table

If you want to attach data other than the table aAtom and business table, you can directly operate the object items here

src/module/test-party/backend/src/service/party.js

async select({ atomClass, options, items, user }) {
  // select
  for (const item of items) {
    this._getMeta(item);
  }
}

write

The business logic of action write generally performs the following operations:

  1. Modify the item’s fields of business table

src/module/test-party/backend/src/service/party.js

async write({ atomClass, key, item, user }) {
  // update party
  await this.ctx.model.party.update({
    id: key.itemId,
    personCount: item.personCount,
    partyTypeId: item.partyTypeId,
  });
}

delete

The business logic of action delete generally performs the following operations:

  1. Delete the item of business table

src/module/test-party/backend/src/service/party.js

async delete({ atomClass, key, user }) {
  // delete party
  await this.ctx.model.party.delete({
    id: key.itemId,
  });
}

Custom Actions

You can implement business-specific operations through custom actions, such as review, publish, etc.

Definition of Custom Action

For example, add a action of review for the atom class party. The configuration of custom action is as follows:

src/module/test-party/backend/src/meta.js

const meta = {
  base: {
    atoms: {
      party: {
        actions: {
          review: {
            code: 101,
            title: 'Review',
            flag: '1',
          },
        },
        flags: {
          1: {
            title: 'Reviewing',
          },
          2: {
            title: 'Reviewed',
          },
        },
      },
    },
  },
};
Name Description
review.code action’s code
review.title action’s title
review.flag action’s flag
flags definition of flags

Basic API Route

The core module a-base implements the unified distribution of custom actions

a-base/backend/src/routes.js

{ method: 'post', path: 'atom/action',
  controller: atom, 
  middlewares: 'transaction',
  meta: { right: { type: 'atom' } },
},

Business API Route

Business module only need to provide business API route, so as to perform business logic codes for the corresponding custom actions

For example, the business API route of module test-party is as follows:

src/module/test-party/backend/src/routes.js

{ method: 'post', path: 'party/action',
  controller: party, 
  middlewares: 'inner', 
  meta: { auth: { enable: false } } },

Business Logic Codes

src/module/test-party/backend/src/service/party.js

async action({ action, atomClass, key, user }) {
  if (action === 101) {
    // change flag
    await this.ctx.meta.atom.flag({
      key,
      atom: { atomFlag: 2 },
      user,
    });
  }
}