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

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

module that logs to stdout is declared by default

async onModuleInit() {
 this.logger.log("drone module is successfully initialized");
}
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

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

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

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

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

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

create a document with the data of db.ModelInput

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

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

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

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

const 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 }

const 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

const 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 }

const 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

const 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

const 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

const 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

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

return the number of documents that match the query condition

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

aggregate the ModelInsight of the documents that match the query condition

const 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.
async _preCreate(data: DataInputOf<db.DroneInput, db.Drone>):
Promise<DataInputOf<db.DroneInput, db.Drone>> {
  if (data.name === 'myDrone') throw new Error('No more myDrone');
  return data;
}
1.5. Custom fields and methods
Custom fields or methods that are needed in the service can be declared as class properties as follows.
@Service('DroneService')
export class DroneService extends DbService(db.droneDb) {
  #myCustomField = "this is my custom field";
  async myCustomMethod(arg: string) {
    this.logger.info("this is my custom method");
    return arg;
  }
}

2. Customizable injections

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

Define an external API class

import { Logger } from '@core/common';
import axios, { type AxiosInstance } from 'axios';
export class MyApi {
  url: string;
  #api: AxiosInstance;
  #logger = new Logger('MyApi');
  constructor(url: string) {
    this.url = url;
    this.#api = axios.create({ baseURL: url, timeout: 5000 });
  }
  async getSomething() {
    try {
      const { data } = await this.#api.get('/something');
      return data;
    } catch (e) {
      this.#logger.warn("Failed to get from MyApi: " + e.message);
      return null;
    }
  }
}

Export the module

export * from './myApi';

Server setup

// import ...
import { MyApi } from '@<APP_NAME>/nest';
export const registerDroneModule = (url?: string) => {
  const myApi = new MyApi(url ?? "http://localhost");
  return databaseModuleOf(
    {
      constant: cnst.droneCnst,
      database: db.droneDb,
      signal: DroneSignal,
      service: DroneService,
      uses: { myApi }, // inject variable here
    },
    allSrvs
  );
};

Use in service

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

3. Utility Decorators

3.1. @Interval, @Cron
A decorator that defines a job that runs periodically.
import { Cron, Interval } from '@core/server';
@Service("DroneService")
export class DroneService extends DbService(db.droneDb) {
 @Interval(1000) // ms
 async doSomeIntervalJob() {
   this.logger.log("interval job done");
 }
 @Cron("* * * * * *")
 async doSomeCronJob() {
   this.logger.log("cron job done");
 }
}
3.2. @Try
A decorator that catches exceptions that occur during method execution and handles them quietly.
import { Try } from '@core/server';
@Service("DroneService")
export class DroneService extends DbService(db.droneDb) {
 @Try()
 async trySomething() {
   throw new Error("Some Error")
 }
 async doStuff() {
   // ...
   await trySomething(); // error is not thrown
   // ...
 }
}
3.3. @Transaction
A decorator that wraps multiple database operations into a single transaction.
import { Transaction } from '@core/server';
import type * as srv from '../srv';
@Service('DroneService')
export class DroneService extends DbService(db.droneDb) {
 @Srv() missionService: srv.MissionService;
 @Transaction()
 async applyMission(missionId: string) {
   const mission = await this.missionService.getMission(missionId);
   await drone.setMission(missionId).save();
   return drone;
 }
}
Released under the MIT License
Official Akan.js Consulting onAkansoft
Copyright © 2025 Akan.js. All rights reserved.
System managed bybassman