Project structure
1. Changing items
- Starting with
extension version 1.0.12
, If the Node.js version configured on the user'sdesktop or laptop
is below Node.js 18, the extension will not function. - Default framework of
Application lambda
orLong-Term Service
is changed from @rdk/lambda → @cals-framework/lambda - Adjustments or deployments of the
Application Lambda
orLong-Term Service
may vary depending on framework changes. - When modifying and deploying an existing
Application Lambda
orLong-Term Service
, the following tasks must be performed due to the changes in the framework. (※ Please refer to the subsequent change guide for detailed changes and instructions.)- Rename
index.js
toapp.js
and update the source code information accordingly, - Modify the method in
controller.js
- Change the configuration file at the bottom of the
config/
folder fromJSON
format toJavaScript
format. - Update files associated with the framework change, including:
LambdaBaseConstant
,ApplicationLambdaException
,LambdaBaseLib
,ApplicationLambdaBaseModel
,LambdaBaseUtil
,BaseHandler
,BaseController
,BaseService
andBaseDAO
. - After clicking the
Migration
button in theExtension – localExplorer
, proceed with the deployment process.
- Rename
2. Folder structure explanation
No. | Folder name | Explanation |
---|---|---|
1 | config | Contains configuration values that define the execution environment. |
2 | constant | A folder that consolidates constants used throughout the project. |
3 | exception | A folder for storing class files that define exceptions. |
4 | lib | A folder for storing class files using external libraries. |
5 | model | A space for storing class files of model definition. |
6 | query | The site gathers Query XML files. |
7 | src | Folder gathers business-related source code to be used in the project. |
8 | util | Manages commonly used source code shared across the project. |
3. File structure explanation
3.1. File is used to distinguish Local and Production environments automatically based on environment variables value. /config/projectBaseConfig.js
const { ProjectBaseConfigDev } = require('./projectBaseConfigDev')
const { ProjectBaseConfigProd } = require('./projectBaseConfigProd')
module.exports.ProjectBaseConfig = process.env.NODE_ENV !== 'production' ? ProjectBaseConfigDev : ProjectBaseConfigProd
3.2. The file to configure the environment to debug in the Local
environment. /config/projectBaseConfigDev.js
'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 variable by constructor
*
* @constructor
*/
// can modify from this area
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'
this.Logger.LEVEL = LogLevel.DEBUG
this.Logger.ParamEnabled = false
this.Logger.ResultEnabled = false
this.Logger.DBLogEnabled = true
this._DB.ENGINE = 'mysql'
this._DB.CONNECTION_TYPE = DB_CONNECTION_TYPE.CONFIG
this._DB.HOST = '{{dbHost}}'
this._DB.USER = '{{dbUser}}'
this._DB.PASSWORD = '{{dbPassword}}'
this._DB.SCHEMA = '{{dbSchema}}'
}
}
module.exports.ProjectBaseConfigDev = ProjectBaseConfigDev
3.3. This is environment config file for operation in product environment. (Support Key: is displayed at YES status only.)/config/projectBaseConfigProd.js
'use strict'
const { LambdaBaseConfig, DB_CONNECTION_TYPE, LogLevel, NODE_ENV_TYPE } = require('@cals-framework/lambda')
const { resolve } = require('path')
console.log(`process.env.AWS_REGION: ${process.env.AWS_REGION}`)
/**
* ProjectBaseConstant class
*
* @class
*/
class ProjectBaseConfigProd extends LambdaBaseConfig {
/**
* Create constant variable by construction
*
* @constructor
*/
// Can edit from this part
constructor() {
super()
this.NODE_ENV = NODE_ENV_TYPE.PRODUCTION
this.OBJ_MAPPER.path.push(resolve(__dirname, '../query/mysql/mysql.xml'))
this.OBJ_MAPPER.namespace.mysql = 'mysql'
this.Logger.LEVEL = LogLevel.DEBUG
this.Logger.ParamEnabled = false
this.Logger.ResultEnabled = false
this.Logger.RdkLogEnabled = false
this.Logger.DBLogEnabled = true
this._DB.ENGINE = 'mysql'
this._DB.CONNECTION_TYPE = DB_CONNECTION_TYPE.SECRETS_MANAGER
this._DB.HOST = 'demo'
this._DB.USER = ''
this._DB.PASSWORD = ''
this._DB.SCHEMA = ''
this._CACHE_DB.CONNECTION_TYPE = DB_CONNECTION_TYPE.CONFIG
this._CACHE_DB.ENGINE = ''
this._CACHE_DB.HOST = '127.0.0.1'
this._CACHE_DB.PORT = 6379
}
}
module.exports.ProjectBaseConfigProd = ProjectBaseConfigProd
3.4. The file manages variables within the project. /constant/projectBaseConstant.js
'use strict'
/**
* @fileoverview file containing constant variable
*/
/**
* 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 {
/**
* Create constant variables by constructor.
* @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
}
}
}
3.5. The file creates a class including an external library to be used within the project. /lib/lambdaLib.js
'use strict'
/**
* @fileoeverview Sample for Library module
* lambdaLib.js
*/
const os = require('os')
const { LambdaBaseLib } = require('@cals-framework/lambda')
/**
* Lambda sample for library module
* @module LambdaLib
* @example
* const RdkLambdaLib = require('./lambdaLib.js)
* const clsRdkLambdaLib = new RdkLambdaLib()
* @desc Lambda sample for library module
*/
module.exports = class LambdaLib extends LambdaBaseLib {
/**
* Create Library object by constructor
* @constructs
* @param
*/
constructor () {
super()
this.homeDir = os.homedir()
this.hostName = os.hostname()
this.getTempDir = getTempDir
}
/**
* getTempDir function
* @function
* @param
* @desc return temp Directory
*/
getTempDir() {
return this.path.resolve(os.tmpdir())
}
}
3.6. The file defines a Model
object to be used within the project. /model/lambdaModel.js
'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 for 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
3.7. The file creates source code such as validation for received events and default value according to MVC
pattern. /src/controller.js
'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)
this.objReturn = await this.clsService.runMethod({ objRequestParams: this.objRequestParams, objReturn: this.objReturn })
calsLogger.result(this.objReturn)
return this.objReturn
}
}
3.8. The file defines a function that is responsible for executing business logic. /src/service.js
'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 register data.
const SampleAddDataModel = require('../model/lambdaModel').SampleAddDataModel
const objSampleAddDataModel = new SampleAddDataModel()
// 2. Register data in data registering module.
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 edit up to this part
}
3.9. The file which is responsible for executing SQL
queries related to the database.
/src/dao.js
'use strict'
const { ApplicationDAO, calsLogger } = require('@cals-framework/lambda')
const ProjectBaseConstant = require('../constant/projectBaseConstant')
module.exports = class DAO extends ApplicationDAO {
// can edit form this part
async addData ({ objDAOParams, objReturn }) {
calsLogger.param(objDAOParams)
const objDAOReturn = await this.insert({
sQueryId: 'insertData',
objParam: objDAOParams,
objReturn
})
calsLogger.result(objDAOReturn)
return objDAOReturn
}
}
3.10. The file gathers source code created by project utility. /util/rdkProjectBaseUtil.js
'use strict'
/**
* @fileoeverview Sample for Util module
* Module lambda util Base
*/
const { RdkLambdaBaseUtil } = require('@cals-framework/lambda')
const LambdaLib = require('../lib/lambdaLib')
const clsLambdaLib = new LambdaLib()
/**
* Sample for Util module
* @module RdkProjectBaseUtil
* @example
* const RdkProjectBaseUtil = require('./rdkProjectBaseUtil.js')
* const clsRdkProjectBaseUtil = new RdkProjectBaseUtil()
* @desc sample for Util module
*/
/**
* sample for Util module
* @class
*/
module.exports = class RdkProjectBaseUtil extends RdkLambdaBaseUtil {
constructor () {
super()
this.getOsInfo = getOsInfo
}
}
/**
* sample for OS information returning function
* @function
* @desc Util function returning OS information.
*/
const getOsInfo = () => {
return {
hostName: clsLambdaLib.hostName,
homeDir: clsLambdaLib.homeDir,
tmpDir: clsLambdaLib.getTempDir()
}
}
3.11. The file assigns Handler
to execute lambda
projects. /app.js
'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
4. Framework Context
- Framework Utility
Class name | Explanation |
---|---|
CompareUtility | A utility containing functions frequently used for comparing values. |
ConvertUtility | A utility containing functions frequently used for converting values. |
RandomUtility | A utility containing functions frequently used with random operations, such as generating random integer numbers. |
StringUtility | A utility containing functions related to string manipulation, commonly used throughout the project. |
FsUtility | A utility containing functions related to file system operations, frequently used within the project. |
// Destructuring method
const { calsLogger, CompareUtility, ConvertUtility, RandomUtility, StringUtility, FsUtility } = require('@cals-framework/lambda')
// variable assignment method
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..
// Use for the case that developer want to debug by log
calsLogger.param(“param log..”)
// => 2024.01.12.T08:46:18.863 [PARAM] - [PROJECT] param log..
// Use for checking parameter
calsLogger.result(“result log..”)
// => 2024.01.12.T08:46:18.863 [RESULT] - [PROJECT] result log..
// Use to check return function
calsLogger.error(“error log..”)
// => 2024.01.12.T08:46:18.863 [ERROR] - [PROJECT] error log..
// use for the case that an error log is left
// 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')
- Exception list
Exception Name | Explanation |
---|---|
AlreadyExistException | An error class triggered when data exists. |
DataSQLException | An error class triggered when an issue arises during SQL execution. |
InvalidRequestException | An error class triggered when an invalid request is made. |
MultiDataSelectException | An error class triggered when multiple data entries are accidentally retrieved. |
NoDataException | An error class triggered when a database search request yields no result. |
OperationFailException | An error class triggered when an issue occurs during the execution of a specific operation. |
ParameterNonExistException | An error class triggered when a required parameter for a request is missing. |
ApplicationLambdaException | An error class used within the framework for other errors. |
WrongConfigException | |
CalsSdkExecuteException | |
LambdaBaseException | |
DBConnectionException | |
NoPreferenceException | |
LockObjectException |
// Destructuring method
const { AlreadyExistException } = require('@cals-framework/lambda')
throw new AlreadyExistException()
// variable assignment method
const DataSQLException = require('@cals-framework/lambda').DataSQLException
throw new DataSQLException()