Skip to content

Project structure

1. Folder structure explanation

Alt text

1.1. A space for defining environment configuration values.
1.2. A folder that gathers constants used within the project.
1.3. A folder for storing class files defining Exception
1.4. A folder for storing class files using external libraries.
1.5. A space for storing class files of model definition.
1.6. A location for query XML files.
1.7. A folder for storing business-related source code used in the project.
1.8. A folder for managing common source code used in the project.

2. File structure explanation


2.1. config

/projectBaseConfigDev.js : is a config file to debug in Local environment.

 "use strict";


const {
 LambdaBaseConfig,
 DB_CONNECTION_TYPE,
 LogLevel,
 NODE_ENV_TYPE,
} = require("@cals-framework/lambda");
const { resolve } = require("path");


/**
* ProjectBaseConstant class
*
* @class
*/
class ProjectBaseConfigDev extends LambdaBaseConfig {
 /**
  * Create constant variables with a  constructor
  *
  * @constructor
  */


 // Can modify from this part
 constructor() {
   super();


   this.NODE_ENV = NODE_ENV_TYPE.DEVELOPMENT;


   this.OBJ_MAPPER.path.push(resolve(__dirname, "../query/mysql/mysql.xml"));
   this.OBJ_MAPPER.namespace.mysql = "mysql";


   // A Variables that can control the output range of log
   this.Logger.LEVEL = LogLevel.DEBUG;
   // A variables can control whether calsLogger.param active or not
   this.Logger.ParamEnabled = false;
   // A variables can control whether calsLogger.result active or not
   this.Logger.ResultEnabled = false;
      // A variables control whether query 로깅 active or not
   this.Logger.DBLogEnabled = true;




   this._DB.ENGINE = "mysql";
      // This connection is used for development purpose
   this._DB.CONNECTION_TYPE = DB_CONNECTION_TYPE.CONFIG;
      // Input host of DB to be used for test. (Generally, local DB uses 127.0.0.1 is used)
   this._DB.HOST = "{{dbHost}}";
      // Input user name of DB to be used for test. (Generally, local DB uses root.)
   this._DB.USER = "{{dbUser}}";
      // Input user password of DB to be used for test.
   this._DB.PASSWORD = "{{dbPassword}}";
      // Input schema of DB to be used for test.
   this._DB.SCHEMA = "{{dbSchema}}";
 }
}
module.exports.ProjectBaseConfigDev = ProjectBaseConfigDev;

2.2. constant

/projectBaseConstant.js : is file to organize constants used within project.

'use strict'
/**
* @fileoverview file containing constant variables
*/


/**
* ProjectBaseConstant
* @module ProjectBaseConstant
* @example
* const ProjectBaseConstant = require('../constant/projectBaseConstant')
* const clsProjectBaseConstant = new ProjectBaseConstant()
*/


const { AppLambdaBaseConstant } = require('@cals-framework/lambda')


/**
* ProjectBaseConstant class
* @class
*/


module.exports = class ProjectBaseConstant extends AppLambdaBaseConstant {
 /**
  * Creating constant variables with constructors
  * @constructor
  */


 // can modify from this part 
 constructor () {
   super()
 }


 static ERROR_MESSAGE = {
   NO_AFFECTED_QUERY: 'NO AFFECTED QUERY'
 }
 static QUERY_INFO = {
   selectTest1: {
     name: 'selectTest1',
     type: this.ORM_QUERY_TYPE.SELECT
   }
 }
}

2.3. lib

/lambdaLib.js : this file creates a class including an external library to be used within the project.

'use strict'
/**
* @fileoeverview Sample Library module 
* lambdaLib.js
*/
const os = require('os')
const { LambdaBaseLib } = require('@cals-framework/lambda')


/**
* Lambda  Sample Library module 
* @module LambdaLib
* @example
* const RdkLambdaLib = require('./lambdaLib.js)
* const clsRdkLambdaLib = new RdkLambdaLib()
* @desc Lambda  Sample Library module 
*/
module.exports = class LambdaLib extends LambdaBaseLib {
 /**
  * Creating Library object by the constructor 
  * @constructs
  * @param
  */
 constructor () {
   super()
   this.homeDir = os.homedir()
   this.hostName = os.hostname()
   this.getTempDir = getTempDir
 }


 /**
  * getTempDir function
  * @function
  * @param
  * @desc return to temp Directory 
  */
 getTempDir() {
   return this.path.resolve(os.tmpdir())
 }
}

2.4. model

/lambdaModel.js : This file defines a Model object to be used within the project.

'use strict'
/**
* @fileoeverview Sample for Model module
* lambdaModel.js
*/


const { ApplicationLambdaBaseModel } = require('@cals-framework/lambda')


/**
*Sample for Model module
* @module LambdaModel
* @example
* const LambdaModel = require('./lambdaModel.js')
* const clsLambdaModel = new LambdaModel()
* @desc Sample Model module
*/
class SampleAddDataModel extends ApplicationLambdaBaseModel {
 constructor () {
   super()
   this.sampleName = ''
   this.sampleDesc = ''
 }
}
exports.SampleAddDataModel = SampleAddDataModel


class SampleUpdateDataModel extends ApplicationLambdaBaseModel {
 constructor () {
   super()
   this.sampleName = ''
   this.sampleDesc = ''
 }
}
exports.SampleUpdateDataModel = SampleUpdateDataModel

2.5. src

/controller.js : This file contains the source code for validating the received event values and setting default values according to the MVC pattern.

'use strict'


const { BaseController, CompareUtility, ParameterNonExistException, calsLogger } = require('@cals-framework/lambda')
const Service = require('./service')


module.exports = class Controller extends BaseController {
 constructor ({ event, context }) {
   super({ event, context })
   this.event = event
   this.context = context


      this.calsContext.serviceContext === undefined
       ? this.clsService = new Service()
       : typeof this.calsContext.serviceContext !== 'undefined'
       ? this.calsContext.serviceContext = new Service()
       : this.clsService = this.calsContext.serviceContext
 }


 async process () {
   calsLogger.param(this.event, this.context)


   // Todo : Check validity of parameter , check session
   this.objRequestParams.sampleName = 'test1'
   this.objRequestParams.sampleDesc = 'test1'
   if (CompareUtility.isEmpty(this.objRequestParams.sampleName)) {
     throw new ParameterNonExistException('sampleName')
   }
   if (CompareUtility.isEmpty(this.objRequestParams.sampleDesc)) {
     throw new ParameterNonExistException('sampleDesc')
   }


   this.objReturn = await this.clsService.runMethod({ objRequestParams: this.objRequestParams, objReturn: this.objReturn })


   calsLogger.result(this.objReturn)
   return this.objReturn
 }
}

/service.js : This file contains the functions that implement the business logic.

'use strict'


const { BaseService, calsLogger } = require('@cals-framework/lambda')
const { NoAffectedDataException } = require('../exception/lambdaException')
const ProjectBaseConstant = require('../constant/projectBaseConstant')
const DAO = require('./dao')


module.exports = class Service extends BaseService {
 constructor () {
   super()


      this.calsContext.daoContext === undefined
        ? this.clsDAO = new DAO()
        : typeof this.calsContext.daoContext !== 'undefined'
        ? this.calsContext.daoContext = new DAO()
        : this.clsDAO = this.calsContext.daoContext
 }


 async runMethod ({ objRequestParams, objReturn }) {
   calsLogger.param(objRequestParams)
   // 1. Create model to register data 
   const SampleAddDataModel = require('../model/lambdaModel').SampleAddDataModel
   const objSampleAddDataModel = new SampleAddDataModel()


   // 2. Register data, register data in model 
   objSampleAddDataModel.sampleName = objRequestParams.sampleName
   objSampleAddDataModel.sampleDesc = objRequestParams.sampleDesc


   // 3. Input data
   const objAddReturn = await this.clsDAO.addData({ objDAOParams: objSampleAddDataModel, objReturn })
   if (objAddReturn.affectedRows === 0) {
     throw new NoAffectedDataException(ProjectBaseConstant.ERROR_MESSAGE.NO_AFFECTED_QUERY)
   }


   calsLogger.result(objReturn)
   return objReturn
 }
 // can modify up to here 
}

/dao.js : is the file that accesses database and execute SQL.

'use strict'

const { ApplicationDAO, calsLogger } = require('@cals-framework/lambda')
const ProjectBaseConstant = require('../constant/projectBaseConstant')

module.exports = class DAO extends ApplicationDAO {
 // can modify from this part
 async addData ({ objDAOParams, objReturn }) {
   calsLogger.param(objDAOParams)
  
   const objDAOReturn = await this.insert({
     sQueryId: 'insertData',
     objParam: objDAOParams,
     objReturn
   })
  
   calsLogger.result(objDAOReturn)
   return objDAOReturn
 }
}

2.6. util

/rdkProjectBaseUtil.js : This file contains a utility source created by the utility in the project.

'use strict'
/**
* @fileoeverview Sample for module Util 
* lambda util Base module
*/
const { RdkLambdaBaseUtil } = require('@cals-framework/lambda')
const LambdaLib = require('../lib/lambdaLib')
const clsLambdaLib = new LambdaLib()
/**
* Sample module Util
* @module RdkProjectBaseUtil
* @example
* const RdkProjectBaseUtil = require('./rdkProjectBaseUtil.js')
* const clsRdkProjectBaseUtil = new RdkProjectBaseUtil()
* @desc Sample module Util
*/
/**
* Sample for module Util
* @class
*/
module.exports = class RdkProjectBaseUtil extends RdkLambdaBaseUtil {
 constructor () {
   super()
   this.getOsInfo = getOsInfo
 }
}
/**
* Sample function to return OS information
* @function
* @desc function to return OS information
*/
const getOsInfo = () => {
 return {
   hostName: clsLambdaLib.hostName,
   homeDir: clsLambdaLib.homeDir,
   tmpDir: clsLambdaLib.getTempDir()
 }
}

2.7. app.js

The file that specifies the handler required to run the Lambda project.

'use strict'

const { BaseHandler, calsLogger } = require('@cals-framework/lambda')
const { ProjectBaseConfig } = require('./config/projectBaseConfig')
const Controller = require("./src/controller")


class LambdaHandler extends BaseHandler {
 process(event, context) {
   calsLogger.debug('Project Start')
   return Promise.resolve(new Controller({ event, context }).handle())
 }
}

exports.handler = new LambdaHandler(new ProjectBaseConfig()).handle

3. Framework Context

3.1. logger & Utility

Class nameExplanation
calsLoggerObject Logger provided in Lambda Framework
CompareUtilityUtility that collects frequently used functions for comparing values
ConvertUtilityUtility that collects frequently used functions for converting values
RandomUtilityUtility that collects frequently used functions related to random operations, such as returning integers
StringUtilityUtility that collects frequently used functions for string values
FsUtilityUtility that collects frequently used functions for file system
// Destructuring method 
const { calsLogger, CompareUtility, ConvertUtility, RandomUtility, StringUtility, FsUtility } = require('@cals-framework/lambda')


// Variables allocation method
const calsLogger = require('@cals-framework/lambda').calsLogger
const CompareUtility = require('@cals-framework/lambda').CompareUtility
const ConvertUtility = require('@cals-framework/lambda').ConvertUtility
const RandomUtility = require('@cals-framework/lambda').RandomUtility
const StringUtility = require('@cals-framework/lambda').StringUtility
const FsUtility = require('@cals-framework/lambda').FsUtility


// calsLogger
calsLogger.debug(“debug log..”)
// => 2024.01.12.T08:46:18.863 [DEBUG] - [PROJECT] debug log..
// it can be used when developer want to debug log 
calsLogger.param(“param log..”)
// => 2024.01.12.T08:46:18.863 [PARAM] - [PROJECT] param log..
// It is used to check parameter 
calsLogger.result(“result log..”) 
// => 2024.01.12.T08:46:18.863 [RESULT] - [PROJECT] result log..
// It is used to check return value of function
calsLogger.error(“error log..”) 
// => 2024.01.12.T08:46:18.863 [ERROR] - [PROJECT] error log..
// It is used when leave error log.


// CompareUtility
CompareUtility.isEmpty(null) // => Return true
CompareUtility.isNotEmpty(null) // => Return false


// ConvertUtility
ConvertUtility.convertCharToBool('1') // => Return true
ConvertUtility.convertNullToEmpty(null) // => Return ''
ConvertUtility.convertStringToInteger('123') // => Return 123


//RandomUtility
RandomUtility.getRandomInt(0, 9) // => Randomly returns a value between 0 and 9
RandomUtility.getUuid() // => Return a 32-digit identifier


// StringUtility
StringUtility.slash('C:\test\path') // => Return 'C:/test/path'
StringUtility.isNonAscii('안녕하세요') // => Return true
StringUtility.lpad('abc', 10, '0') // => Return '000000abc'
StringUtility.rpad('abc', 10, '0') // => Return 'abc000000'
StringUtility.nextLetter('a') // => Return 'b'
StringUtility.getCharSeq().getCharByIndex(27) // => Returns a unique sequence of alphabetic characters based on an index


// FsUtility
FsUtility.existsPath('/temp') // => Return true
FsUtility.writeFile('/temp/file1.txt', 'Hello World')
FsUtility.writeFileAsync('/temp/file2.txt', 'Sample File')
.then(() =>{
console.log('Write Complete!')
})
.catch((err) => {
console.err(`What happens: ${err}`)
})
FsUtility.readDirectory('/temp') // => Return ['file1.txt', 'file2.txt']
FsUtility.readFile('/temp/file1.txt') // => Return 'Hello World'
FsUtility.rmASync('/temp/file2.txt')
.then(() => {
console.log('File Removed.')
})
.catch((err) => {
console.error(`What happens: ${err}`)
})
FsUtility.createDirectory('/temp/newDir')

3.2. Exception

Exception nameExplanation
AlreadyExistExceptionError class that occurs when data already exists.
DataSQLExceptionError class that occurs when there is a problem executing SQL.
InvalidRequestExceptionError class that occurs when an invalid request is made.
MultiDataSelectExceptionError class that occurs when multiple data is selected unintentionally.
NoDataExceptionError class that occurs when no data is found in the request message or database query results.
OperationFailExceptionError class that causes problems when executing a specific operation.
ParameterNonExistExceptionError class that occurs when no parameter is found in the request message.
// // Destructuring allocation method 
const { AlreadyExistException } = require('@cals-framework/lambda')
throw new AlreadyExistException()
// variables allocation method
const DataSQLException = require('@cals-framework/lambda').DataSQLException
throw new DataSQLException()