model.service.ts

It is responsible for processing actual business logic. It has one business logic per unit request, and processes it, modifies and saves the database, and returns the result value.

1. Methods & variables

1.1. Predefined Variables
Predefined variables that are available in the service class.
<MODEL_NAME>Model

database model declared in model.document.ts

1async loadMyDrone() {
2 const drone = await this.droneModel.loadDroneByName("myDrone");
3 return drone;
4}
logger

module that logs to stdout is declared by default

1async initialize() {
2 this.logger.log("drone module is successfully initialized");
3}
1.2. Predefined Methods
Predefined methods that are automatically created for all service classes.
getModel(id: string)

load the document with the corresponding id, and return an error if it does not exist

1const drone = await this.getDrone("ObjectId");
loadModel(id: string)

load the document with the corresponding id, and return null if it does not exist

1const drone = await this.loadDrone("ObjectId");
loadModelMany(ids: string[])

load the documents with the corresponding ids, and return an array of documents or nulls

1const drones = await this.loadDroneMany(["ObjectId", "ObjectId"]);
createModel(data: db.ModelInput)

create a document with the data of db.ModelInput

1const drone = await this.createDrone({ name: "myDrone" });
updateModel(id: string, data: db.ModelInput)

update the document with the corresponding id, and return the updated document

1const drone = await this.updateDrone("ObjectId", { name: "newName" });
removeModel(id: string)

soft-delete the document with the corresponding id, and return the deleted document

1const drone = await this.removeDrone("ObjectId"); // drone.status = "inactive"
1.3. Query based methods
Predefined methods that are automatically created based on the query keys defined in model.constant.ts.
list<Query_KEY>(...queryArgs: QueryArgs, option?: ListQueryOption)

return a list of documents that match the query condition ListQueryOption = { skip?: number, limit?: number, sort?: Sort, sample?: boolean }

1const drones = await this.listByName("myDrone"); // db.Drone[]
listIds<Query_KEY>(...queryArgs: QueryArgs, option?: ListQueryOption)

return a list of document ids that match the query condition

1const droneIds = await this.listIdsByName("myDrone"); // string[]
find<Query_KEY>(...queryArgs: QueryArgs, option?: FindQueryOption)

return a document that matches the query condition, or null if it does not exist FindQueryOption = { skip?: number, sort?: Sort, sample?: boolean }

1const drone = await this.findByName("myDrone"); // db.Drone | null
findId<Query_KEY>(...queryArgs: QueryArgs, option?: FindQueryOption)

return a document id that matches the query condition, or null if it does not exist

1const droneId = await this.findIdByName("myDrone"); // string | null
pick<Query_KEY>(...queryArgs: QueryArgs, option?: FindQueryOption)

return a document that matches the query condition, or throw an error if it does not exist

1const drone = await this.pickByName("myDrone"); // db.Drone
pickId<Query_KEY>(...queryArgs: QueryArgs, option?: FindQueryOption)

return a document id that matches the query condition, or throw an error if it does not exist

1const droneId = await this.pickIdByName("myDrone"); // string
exists<Query_KEY>(...queryArgs: QueryArgs)

return true if a document that matches the query condition exists, or false if it does not exist

1const droneExists = await this.existsByName("myDrone"); // string | boolean
count<Query_KEY>(...queryArgs: QueryArgs)

return the number of documents that match the query condition

1const droneCount = await this.countByName("myName"); // number
insight<Query_KEY>(...queryArgs: QueryArgs)

aggregate the ModelInsight of the documents that match the query condition

1const droneInsight = await this.insightByName("myDrone"); // cnst.DroneInsight
1.4. Customizable middleware methods
Middleware methods that can be involved in the data processing process, which can be overridden and used as needed.
_preCreate(data)
A function that can be added to change/validate input data before creating a document with this.createModel.
1async _preCreate(data: DataInputOf<db.DroneInput, db.Drone>):
2Promise<DataInputOf<db.DroneInput, db.Drone>> {
3  if (data.name === 'myDrone') throw new Error('No more myDrone');
4  return data;
5}
1.5. Custom fields and methods
Custom fields or methods that are needed in the service can be declared as class properties as follows.
1@Service('DroneService')
2export class DroneService extends DbService(db.droneDb) {
3  #myCustomField = "this is my custom field";
4
5  async myCustomMethod(arg: string) {
6    this.logger.info("this is my custom method");
7    return arg;
8  }
9}

2. Customizable injections

2.1. @Srv - connecting with other services
A decorator that allows injection of other services to be used.
1import type * as srv from '../srv';
2
3@Service('DroneService')
4export class DroneService extends DbService(db.droneDb) {
5  @Srv() missionService: srv.MissionService;
6
7  async applyMission(missionId: string) {
8    const mission = await this.missionService.getMission(missionId);
9    await drone.setMission(missionId).save();
10    return drone;
11  }
12}
2.2. @Use - inject variables
A decorator that allows injection of variables or classes created outside the service.

Define an external API class

1import { Logger } from '@core/common';
2import axios, { type AxiosInstance } from 'axios';
3
4export class MyApi {
5  url: string;
6  #api: AxiosInstance;
7  #logger = new Logger('MyApi');
8
9  constructor(url: string) {
10    this.url = url;
11    this.#api = axios.create({ baseURL: url, timeout: 5000 });
12  }
13
14  async getSomething() {
15    try {
16      const { data } = await this.#api.get('/something');
17      return data;
18    } catch (e) {
19      this.#logger.warn("Failed to get from MyApi: " + e.message);
20      return null;
21    }
22  }
23}

Export the module

1export * from './myApi';

Server setup

1// import ...
2import { MyApi } from '@<APP_NAME>/nest';
3
4export const registerDroneModule = (url?: string) => {
5  const myApi = new MyApi(url ?? "http://localhost");
6  return databaseModuleOf(
7    {
8      constant: cnst.droneCnst,
9      database: db.droneDb,
10      signal: DroneSignal,
11      service: DroneService,
12      uses: { myApi }, // inject variable here
13    },
14    allSrvs
15  );
16};

Use in service

1@Service('DroneService')
2export class DroneService extends DbService(db.droneDb) {
3 @Use() myApi: MyApi;
4
5 async getSomething(){
6   const something = await this.myApi.getSomething();
7   return something;
8 }
9}
2.3. @Websocket
Inject a WebSocket instance into the service to use for real-time data transmission and reception.
1@Service('DroneService')
2export class DroneService extends DbService(db.droneDb) {
3 @Websocket() websocket: Websocket<DroneSignal>;
4
5 async publishDroneTmtc() {
6   this.websocket.droneTmtcUpdated(drone.id, drone.tmtc);
7 }
8}
2.4. @Queue
Inject a job queue into the service to process asynchronous jobs.
1@Service('DroneService')
2export class DroneService extends DbService(db.droneDb) {
3 @Queue() droneQueue: Queue<DroneSignal>;
4
5 async queueSomething(droneId: string) {
6   const job = await this.droneQueue.queueSomething(droneId);
7   return job;
8 }
9}

3. Utility Decorators

3.1. @Try
A decorator that catches exceptions that occur during method execution and handles them quietly.
1import { Try } from '@core/server';
2
3@Service("DroneService")
4export class DroneService extends DbService(db.droneDb) {
5
6 @Try()
7 async trySomething() {
8   throw new Error("Some Error")
9 }
10
11 async doStuff() {
12   // ...
13   await trySomething(); // error is not thrown
14   // ...
15 }
16}
3.2. @Transaction
A decorator that wraps multiple database operations into a single transaction.
1import { Transaction } from '@core/server';
2import type * as srv from '../srv';
3
4@Service('DroneService')
5export class DroneService extends DbService(db.droneDb) {
6 @Srv() missionService: srv.MissionService;
7
8 @Transaction()
9 async applyMission(missionId: string) {
10   const mission = await this.missionService.getMission(missionId);
11   await drone.setMission(missionId).save();
12   return drone;
13 }
14}
Released under the MIT License
Official Akan.js Consulting onAkansoft
Copyright © 2025 Akan.js. All rights reserved.
System managed bybassman