@cyklang/cli 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyklang/cli",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "cyklang CLI",
5
5
  "main": "build/index.js",
6
6
  "scripts": {
@@ -17,22 +17,20 @@
17
17
  "author": "",
18
18
  "license": "ISC",
19
19
  "dependencies": {
20
- "@cyklang/core": "^0.3.6",
20
+ "@cyklang/core": "^0.5.0",
21
21
  "commander": "^9.4.0",
22
22
  "dotenv": "^16.0.1",
23
23
  "form-data": "^4.0.0",
24
24
  "inquirer": "^8.2.5",
25
25
  "loglevel": "^1.8.0",
26
26
  "mime-types": "^2.1.35",
27
- "pako": "^2.0.4",
28
- "xml": "^1.0.1"
27
+ "pako": "^2.0.4"
29
28
  },
30
29
  "devDependencies": {
31
30
  "@types/inquirer": "^8.2.4",
32
31
  "@types/mime-types": "^2.1.1",
33
32
  "@types/pako": "^2.0.0",
34
33
  "@types/sax": "^1.2.4",
35
- "@types/xml": "^1.0.8",
36
34
  "nodemon": "^2.0.16",
37
35
  "ts-node": "^10.7.0",
38
36
  "typescript": "4.5.2"
@@ -5,7 +5,8 @@ import { DBClient } from "./DBClient"
5
5
  import * as fs from "fs"
6
6
  import path from "path"
7
7
  import mime from 'mime-types'
8
- import readline from 'readline'
8
+ import inquirer from 'inquirer'
9
+ // import readline from 'readline'
9
10
  import { DBAsset, DBExecuteRequest, ObjectData, parseXML, PrimitiveData } from "@cyklang/core"
10
11
  import FormData from 'form-data'
11
12
 
@@ -37,7 +38,7 @@ class AssetList extends Cmd {
37
38
 
38
39
  const dbClient = new DBClient(this.dbManager)
39
40
  dbClient.selectFromTable('List of Assets', 'cyk_asset',
40
- { fields: 'asset_id,asset_route,asset_last_update,asset_mimetype', sort: options.sort || '1' }
41
+ { fields: 'asset_id,asset_route,asset_auth,asset_access,asset_mimetype,asset_last_update', sort: options.sort || '1' }
41
42
  )
42
43
  }
43
44
  catch (err) {
@@ -53,19 +54,33 @@ class AssetList extends Cmd {
53
54
  interface FileDescriptor {
54
55
  path: string
55
56
  mtime: Date
57
+ id?: number
56
58
  }
57
59
  class AssetUpload extends Cmd {
58
60
 
59
61
  constructor(name: string, description: string) {
60
62
  super(name)
61
63
  this.description(description)
62
- .option('-d --dest <destination>', 'route of destination')
64
+ .option('-d --dest <destination>', 'destination path, directory name')
65
+ .option('-c --clean', 'clean destination path before uploading')
66
+ .option('-y --yes', 'upload list is automatically confirmed')
63
67
  .argument('[sources...]', 'local files or directories to upload as assets to the server')
64
68
  .action(async (sources: any, options: any) => {
65
69
  await this.commandUpload(sources, options)
66
70
  })
67
71
  }
68
72
 
73
+ mimetypeLookup(filename: string): string | false {
74
+ let result: string | false
75
+ if (path.extname(filename) === '.cyk') {
76
+ result = 'application/xml'
77
+ }
78
+ else {
79
+ result = mime.lookup(filename)
80
+ }
81
+ return result
82
+ }
83
+
69
84
  async commandUpload(sources: string[], options: any) {
70
85
 
71
86
  try {
@@ -79,17 +94,21 @@ class AssetUpload extends Cmd {
79
94
  if (dest.substring(0, 1) !== '/') dest = '/' + dest
80
95
  if (dest.substring(dest.length - 1) !== '/') dest = dest + '/'
81
96
 
97
+ if (options.clean) {
98
+ await this.cleanDestination(dest)
99
+ }
100
+
82
101
  for (let ind = 0; ind < sources.length; ind++) {
83
102
  const source = sources[ind]
84
103
  if (fs.existsSync(source) === false) throw 'source ' + source + ' does not exist'
85
104
  const filestat = fs.lstatSync(source)
86
105
  if (filestat.isDirectory() === true) {
87
- await this.uploadDirectory(source, dest)
106
+ await this.uploadDirectory(source, dest, options)
88
107
  }
89
108
  else if (filestat.isFile() === true) {
90
109
  const base = path.parse(source).base
91
110
  logger.debug('upload file ' + source + ' to ' + dest + base)
92
- await this.uploadAsset({path:source, mtime: filestat.mtime}, dest + base)
111
+ await this.uploadAsset({ path: source, mtime: filestat.mtime }, dest + base)
93
112
  }
94
113
  }
95
114
  }
@@ -98,11 +117,27 @@ class AssetUpload extends Cmd {
98
117
  }
99
118
  }
100
119
 
120
+ //----------------------------------------------------------------------------------------------
121
+ // cleanDestination
122
+ //----------------------------------------------------------------------------------------------
123
+
124
+ async cleanDestination(dest: string) {
125
+
126
+ const remoteList = await this.scanAssets()
127
+ for(let ind = 0; ind < remoteList.length; ind++) {
128
+ const fd = remoteList[ind]
129
+ if (fd.path.startsWith(dest)) {
130
+ const url = '/api/admin/assets/' + fd.id
131
+ await this.dbRemote?.apiServer.delete(url)
132
+ }
133
+ }
134
+ }
135
+
101
136
  //----------------------------------------------------------------------------------------------
102
137
  // uploadDirectory
103
138
  //----------------------------------------------------------------------------------------------
104
139
 
105
- async uploadDirectory(source: string, dest: string) {
140
+ async uploadDirectory(source: string, dest: string, options: any) {
106
141
 
107
142
  const localList: FileDescriptor[] = []
108
143
  let dirName: string
@@ -114,28 +149,38 @@ class AssetUpload extends Cmd {
114
149
  dirName = source + '/'
115
150
  }
116
151
 
117
- logger.debug('dirName', dirName)
152
+ logger.debug('options', options)
118
153
 
119
154
  this.scanDir(dirName, localList)
120
155
 
121
- const remoteList: FileDescriptor[] = []
122
- await this.scanAssets(remoteList)
156
+ const remoteList = await this.scanAssets()
123
157
 
124
158
  const uploadList = this.buildUploadList(dirName, dest, localList, remoteList)
125
159
 
126
160
  // logger.info(fileNames.join('\n'))
127
161
  if (uploadList.length === 0) throw 'None file to upload'
128
162
 
129
- const rl = readline.createInterface(process.stdin, process.stdout)
130
- rl.question('Do you want to upload this(these) ' + uploadList.length + ' file(s) (Y/N/y/n) ?', async (reply) => {
131
- rl.close()
132
- if (reply !== 'Y' && reply !== 'y') {
133
- logger.info('upload cancelled')
134
- return
135
- }
163
+ let uploadConfirmed = (options.yes !== undefined)
164
+
165
+ if (uploadConfirmed === false) {
166
+ const reply = await inquirer.prompt({ type: 'confirm', name: 'confirm', message: 'Do you want to upload this(these) ' + uploadList.length + ' file(s) ?' })
167
+ if (reply.confirm === true) uploadConfirmed = true
168
+ }
136
169
 
170
+ if (uploadConfirmed === true) {
137
171
  await this.uploadFiles(dirName, uploadList, dest)
138
- })
172
+ }
173
+
174
+ // const rl = readline.createInterface(process.stdin, process.stdout)
175
+ // rl.question('Do you want to upload this(these) ' + uploadList.length + ' file(s) (Y/N/y/n) ?', async (reply) => {
176
+ // rl.close()
177
+ // if (reply !== 'Y' && reply !== 'y') {
178
+ // logger.info('upload cancelled')
179
+ // return
180
+ // }
181
+
182
+ // await this.uploadFiles(dirName, uploadList, dest)
183
+ // })
139
184
  }
140
185
 
141
186
  //----------------------------------------------------------------------------------------------
@@ -145,32 +190,32 @@ class AssetUpload extends Cmd {
145
190
  buildUploadList(dirName: string, dest: string, localList: FileDescriptor[], remoteList: FileDescriptor[]): FileDescriptor[] {
146
191
  const result: FileDescriptor[] = []
147
192
  const remoteMap = new Map<string, FileDescriptor>()
148
- for(let ind = 0; ind < remoteList.length; ind++) {
193
+ for (let ind = 0; ind < remoteList.length; ind++) {
149
194
  const remote = remoteList[ind]
150
195
  remoteMap.set(remote.path, remote)
151
196
  }
152
- for(let ind = 0; ind < localList.length; ind++ ) {
197
+ for (let ind = 0; ind < localList.length; ind++) {
153
198
  const localDesc = localList[ind]
154
199
  const route = dest + localDesc.path.substring(dirName.length)
155
200
  const remoteDesc = remoteMap.get(route)
156
201
 
157
202
  if (remoteDesc === undefined || remoteDesc.mtime.getTime() + 1000 < localDesc.mtime.getTime()) {
158
203
  if (remoteDesc === undefined) logger.debug('remoteDesc undefined')
159
- else logger.debug('remoteDesc.mtime '+ remoteDesc.mtime.getTime(), 'localDesc.mtime ' + localDesc.mtime.getTime())
204
+ else logger.debug('remoteDesc.mtime ' + remoteDesc.mtime.getTime(), 'localDesc.mtime ' + localDesc.mtime.getTime())
160
205
  logger.info(localDesc.path)
161
206
  result.push(localDesc)
162
207
  }
163
208
  }
164
209
  return result
165
210
  }
166
-
167
-
211
+
212
+
168
213
  //----------------------------------------------------------------------------------------------
169
214
  // scanAssets
170
215
  //----------------------------------------------------------------------------------------------
171
216
 
172
- async scanAssets(result: FileDescriptor[]) {
173
-
217
+ async scanAssets() {
218
+ const result: FileDescriptor[] = []
174
219
  if (this.dbManager === undefined) throw 'dbManager undefined'
175
220
  const dbReq = new DBExecuteRequest()
176
221
  dbReq.selectFromTable = 'cyk_asset'
@@ -181,14 +226,16 @@ class AssetUpload extends Cmd {
181
226
  const tag = parseXML('scanAssets', xmlResult)
182
227
  const objResult = await this.dbManager.scope.structure.objectDataType.parseData(tag, this.dbManager.scope) as ObjectData
183
228
  const rows = (objResult.variables.getData('cyk_asset') as ObjectData).variables
184
- for(let ind = 0; ind < rows.list.length; ind++) {
185
- const {variable: row} = rows.list[ind]
229
+ for (let ind = 0; ind < rows.list.length; ind++) {
230
+ const { variable: row } = rows.list[ind]
186
231
  const record = row.data as ObjectData
232
+ const asset_id = (record.variables.getData('asset_id') as PrimitiveData).value as number
187
233
  const asset_route = (record.variables.getData('asset_route') as PrimitiveData).value as string
188
- const asset_last_update = (record.variables.getData('asset_last_update') as PrimitiveData).value as Date
234
+ const asset_last_update = (record.variables.getData('asset_last_update') as PrimitiveData)?.value as Date
189
235
  // logger.debug('asset_route ' + asset_route,'asset_last_update ' + asset_last_update)
190
- result.push({path: asset_route, mtime: asset_last_update})
236
+ result.push({ path: asset_route, mtime: asset_last_update, id: asset_id })
191
237
  }
238
+ return result
192
239
  }
193
240
 
194
241
  //----------------------------------------------------------------------------------------------
@@ -205,12 +252,12 @@ class AssetUpload extends Cmd {
205
252
  this.scanDir(dirName + fileName + '/', result)
206
253
  }
207
254
  else {
208
- if (mime.lookup(fileName) === false) {
255
+ if (this.mimetypeLookup(fileName) === false) {
209
256
  logger.info(fileName + ' file extension is unknown and will not be uploaded')
210
257
  continue
211
258
  }
212
259
  //const dbAssetExist = this.dbManager?.dbAssetExist()
213
- result.push({path: dirName + fileName, mtime: fstat.mtime})
260
+ result.push({ path: dirName + fileName, mtime: fstat.mtime })
214
261
  // logger.debug(dirName + '/' + fileName)
215
262
  }
216
263
  }
@@ -248,18 +295,18 @@ class AssetUpload extends Cmd {
248
295
  //----------------------------------------------------------------------------------------------
249
296
 
250
297
  async uploadAsset(upload: FileDescriptor, route: string) {
251
- logger.debug('uploadAsset ' + upload.path + ' to route ' + route + ' with mimetype ' + mime.lookup(upload.path))
298
+ logger.debug('uploadAsset ' + upload.path + ' to route ' + route + ' with mimetype ' + this.mimetypeLookup(upload.path))
252
299
 
253
300
  try {
254
301
  let dbAsset: DBAsset | undefined = await this.dbManager?.dbAssetExist(route)
255
302
  if (dbAsset === undefined) {
256
303
  dbAsset = new DBAsset()
257
304
  }
258
- const mimetype = mime.lookup(upload.path)
305
+ const mimetype = this.mimetypeLookup(upload.path)
259
306
  if (mimetype === false) throw 'mimetype false for ' + upload
260
307
  dbAsset.mimetype = mimetype
261
308
  dbAsset.route = route
262
-
309
+
263
310
  // const fstat = fs.statSync(fileName)
264
311
  dbAsset.last_update = upload.mtime
265
312
 
@@ -294,9 +341,9 @@ class AssetUpload extends Cmd {
294
341
  const form = new FormData()
295
342
  form.append('uploadFile', file)
296
343
 
297
- const route = '/upload/cyk_asset/asset_content?asset_id=' + dbAsset.id
344
+ const route = '/api/upload/cyk_asset/asset_content?asset_id=' + dbAsset.id
298
345
  const resp = await this.dbRemote?.apiServer.post(route, form)
299
- if ( resp.status === 200 ) {
346
+ if (resp.status === 200) {
300
347
  logger.info(fileName + ' uploaded')
301
348
  }
302
349
  }
package/src/Cmd.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { DBManager, DBRemote, Structure } from "@cyklang/core";
1
+ import { DBManager, DBRemote, SigninResponse, Structure } from "@cyklang/core";
2
2
  import { Command } from "commander";
3
3
  import dotenv from 'dotenv'
4
4
  import loglevel from 'loglevel'
@@ -14,21 +14,25 @@ export class Cmd extends Command {
14
14
  super(name);
15
15
  this.option('--env <env>', 'path to the environment variables file')
16
16
  }
17
-
18
- async prologue(options: any) {
19
17
 
20
- const dotenvOutput = dotenv.config({path: options.env})
18
+ async prologue(options: any): Promise<SigninResponse> {
19
+
20
+ const dotenvOutput = dotenv.config({ path: options.env })
21
21
  if (dotenvOutput.error !== undefined) throw dotenvOutput.error
22
22
 
23
23
  const structure = new Structure()
24
24
  if (process.env.DBREMOTE_URL === undefined) throw 'DBREMOTE_URL undefined'
25
- logger.debug('DBREMOTE_URL ' + process.env.DBREMOTE_URL)
25
+ logger.debug('Cmd.DBREMOTE_URL ' + process.env.DBREMOTE_URL)
26
26
  const nodeCrypto = new NodeCrypto()
27
27
  this.dbRemote = new DBRemote(structure.scope, process.env.DBREMOTE_URL, nodeCrypto)
28
28
  const login = await this.dbRemote.signin(process.env.USER_NAME, undefined, process.env.USER_PASSWORD)
29
29
  // logger.debug(login)
30
-
30
+
31
31
  this.dbManager = new DBManager(structure.scope, this.dbRemote)
32
32
  await this.dbManager.initialize()
33
+
34
+ return login
35
+
36
+
33
37
  }
34
38
  }
package/src/DBClient.ts CHANGED
@@ -10,6 +10,10 @@ export class DBClient {
10
10
  this.dbManager = dbManager
11
11
  }
12
12
 
13
+ async runQuery() {
14
+
15
+ }
16
+
13
17
  async selectFromTable(title: string, tableName: string, options:
14
18
  { fields: string, sort?: string | undefined, where?: string | undefined, width?: string | undefined }) {
15
19
 
@@ -79,6 +83,22 @@ export class DBClient {
79
83
  logger.error(err)
80
84
  }
81
85
  }
86
+
87
+ async deleteModule(dbname: string) {
88
+
89
+ try {
90
+ const dbModule = await this.dbManager.dbModuleExist(dbname)
91
+
92
+ if (dbModule === undefined) {
93
+ throw ('Module ' + dbname + ' not found')
94
+ }
95
+ await this.dbManager.dbModuleDelete(dbModule)
96
+ }
97
+ catch (err) {
98
+ logger.error(err)
99
+ }
100
+
101
+ }
82
102
  }
83
103
 
84
104
  class List {
@@ -216,6 +236,10 @@ class List {
216
236
  else {
217
237
  result = value.toString()
218
238
  }
239
+
240
+ // replace \n with a space
241
+ result = result.replace(/\n/, ' ')
242
+
219
243
  if (width !== undefined && width !== 0) {
220
244
  if (result.length >= width) {
221
245
  result = result.substring(0, width)
@@ -25,8 +25,9 @@ Otherwise, a new module is inserted in the database. To rename a module, use opt
25
25
  // list
26
26
  this.addCommand(new ModuleList('list', 'List modules'))
27
27
  this.addCommand(new ModuleList('l', 'shortcut for (l)ist'))
28
- // rename
29
-
28
+ // rename **TODO**
29
+ // delete
30
+ this.addCommand(new ModuleDelete('delete', 'delete module from database'))
30
31
  }
31
32
  }
32
33
 
@@ -36,7 +37,7 @@ function getModuleDBName(filePath: string): string {
36
37
  // result = path.basename(filePath, '.xml')
37
38
 
38
39
  const result = path.parse(filePath).name
39
- const identifierRegex = /^[_a-zA-Z][_a-zA-Z0-9]*$/
40
+ const identifierRegex = /^[_a-zA-Z][-_a-zA-Z0-9]*$/
40
41
  if (result.match(identifierRegex) === null) throw 'filename ' + result + ' does not match identifier syntax'
41
42
  return result
42
43
  }
@@ -184,7 +185,7 @@ class ModuleList extends Cmd {
184
185
 
185
186
  const dbClient = new DBClient(this.dbManager)
186
187
  dbClient.selectFromTable('List of Modules', 'cyk_module',
187
- { fields: 'module_id,module_dbname,module_access,module_description', sort: options.sort || '1' })
188
+ { fields: 'module_id,module_dbname,module_auth,module_access,module_description', sort: options.sort || '1' })
188
189
 
189
190
  }
190
191
  catch (err) {
@@ -197,10 +198,10 @@ class ModuleDelete extends Cmd {
197
198
  constructor(name: string, description: string) {
198
199
  super(name)
199
200
  this.description(description)
200
- .argument('[files...]', 'module(s) to delete from the database')
201
- .action(async(files: any, options: any) => {
202
- await this.commandDelete(files, options)
203
- })
201
+ .argument('[files...]', 'module(s) to delete from the database')
202
+ .action(async (files: any, options: any) => {
203
+ await this.commandDelete(files, options)
204
+ })
204
205
  }
205
206
  async commandDelete(files: string[], options: any) {
206
207
  try {
@@ -208,12 +209,17 @@ class ModuleDelete extends Cmd {
208
209
  if (this.dbManager === undefined) throw 'dbManager undefined'
209
210
 
210
211
  if (files.length === 0) throw 'no module to delete'
211
-
212
+ const dbClient = new DBClient(this.dbManager)
213
+ for (let ind = 0; ind < files.length; ind++) {
214
+ const dbname = files.at(ind)
215
+ if (dbname !== undefined)
216
+ dbClient.deleteModule(dbname)
217
+ }
212
218
 
213
219
  }
214
- catch (err){
220
+ catch (err) {
215
221
  logger.error(err)
216
- }
222
+ }
217
223
  }
218
224
  }
219
225
 
@@ -4,59 +4,76 @@ import * as fs from "fs"
4
4
  import loglevel from 'loglevel'
5
5
  import { Cmd } from './Cmd'
6
6
  import { Command } from 'commander'
7
+ import { DBClient } from "./DBClient"
7
8
  const logger = loglevel.getLogger("QueryCommand.ts")
8
9
  logger.setLevel("debug")
9
10
 
10
11
  export class QueryCommand extends Command {
11
12
  constructor(name: string) {
12
13
  super(name)
14
+ this.description('query management')
15
+ this.addCommand(new QueryList('list', 'list queries'))
16
+ this.addCommand(new QueryList('l', 'list queries'))
13
17
  }
14
18
  }
15
19
 
16
- function parseXmlFile(filepath: string, basename: string, xmlSource: string): Tag {
17
- const tag = parseXML(filepath, xmlSource)
18
- if (tag.name !== 'DB.QUERY') {
19
- throw Error('tag ' + tag.name + ', should be <db.query>')
20
- }
21
- const name = tag.attributes.NAME
22
- if (name === undefined) {
23
- throw Error('name attribute is missing')
20
+ //--------------------------------------------------------------------------------------------------------------------
21
+ // class TableList
22
+ //--------------------------------------------------------------------------------------------------------------------
23
+
24
+ class QueryList extends Cmd {
25
+ constructor(name: string, description: string) {
26
+ super(name)
27
+ this.description(description)
28
+ .option('-s --sort <columns>', 'sort list by column numbers (begins with 0) separated by comma')
29
+ .action(async (options: any) => {
30
+ await this.commandList(options)
31
+ })
24
32
  }
25
- if (basename !== name + '.xml') {
26
- throw Error('filename ' + filepath + ' and name ' + name + ' do not correspond')
33
+
34
+ async commandList(options: any) {
35
+ await this.prologue(options)
36
+ if (this.dbManager === undefined) throw 'dbManager undefined'
37
+
38
+ const dbClient = new DBClient(this.dbManager)
39
+ dbClient.selectFromTable('List of Queries', 'cyk_query',
40
+ { fields: 'query_id,query_name,query_auth,query_access,query_description', sort: options.sort || '1' }
41
+ )
27
42
  }
28
- return tag
29
43
  }
30
44
 
31
- async function executeXml(structure: Structure, tag: Tag, xmlSource: string) {
32
- try {
33
- logger.debug('executeXml ' + tag.attributes.NAME)
34
- // structure.setInstructionType("print", new PrintInstructionType(logfilename))
35
- const dbQueryInstructionType = structure.scope.getInstructionType('db.query')
36
- if (dbQueryInstructionType === undefined) {
37
- throw Error('dbQueryInstructionType not found')
38
- }
39
45
 
40
- const scopeParse = new Scope(structure, structure.scope, undefined)
41
- const dbQueryInst = <DBQueryInstruction>await dbQueryInstructionType.parseInstruction(tag, scopeParse)
42
- dbQueryInst.source = xmlSource
43
- const scopeExecute = new Scope(structure, structure.scope, undefined)
44
- await dbQueryInst.execute(scopeExecute)
45
- }
46
- catch (err) {
47
- logger.error(err)
46
+
47
+ //--------------------------------------------------------------------------------------------------------------------
48
+ // class queryData
49
+ //--------------------------------------------------------------------------------------------------------------------
50
+
51
+ class queryData extends Cmd {
52
+
53
+ constructor(name: string, description: string) {
54
+ super(name)
55
+ this.description(description)
56
+ .argument('<query>', 'query name')
57
+ .option('--where <clause_where_sql>', 'criteria in SQL syntax')
58
+ .option('-s --sort <columns>', 'sort by columns positions (begins by 0) separated by comma')
59
+ .option('-w --width <colwidth>', 'columns widths separated by comma')
60
+ .action(async (query, options) => {
61
+ this.commandData(query, options)
62
+ })
48
63
  }
49
- }
50
64
 
51
- async function testQuery(structure: Structure, queryName: string) {
52
- const xmlScript = `
53
- <block>
54
- <object name='result'/>
55
- <db.execute query='${queryName}' result='result' />
56
- <print>string(result)</print>
57
- </block>
58
- `
59
- const script = new Script(structure.scope, 'test', xmlScript)
60
- await script.parseInstructions()
61
- await script.execute()
65
+ async commandData(query: string, options: any) {
66
+ try {
67
+ await this.prologue(options)
68
+ if (this.dbManager === undefined) throw 'dbManager undefined'
69
+
70
+ const dbQuery = await this.dbManager.dbQueryExist(query)
71
+ if (dbQuery === undefined) throw 'query ' + query + ' not found'
72
+
73
+ //DBClient
74
+ }
75
+ catch (err) {
76
+ logger.error(err)
77
+ }
78
+ }
62
79
  }