@cyklang/cli 0.2.3 → 0.3.1

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.
@@ -19,7 +19,7 @@ export class AssetCommand extends Command {
19
19
  this.description(description)
20
20
  this.addCommand(new AssetList('list', 'list assets'))
21
21
  this.addCommand(new AssetList('l', '(l)ist assets'))
22
- this.addCommand(new AssetUpload('upload', 'upload assets from current directory'))
22
+ this.addCommand(new AssetUpload('upload', 'upload assets from sources'))
23
23
  this.addCommand(new AssetUpload('u', '(u)pload assets'))
24
24
  }
25
25
  }
@@ -38,7 +38,7 @@ class AssetList extends Cmd {
38
38
 
39
39
  const dbClient = new DBClient(this.dbManager)
40
40
  dbClient.selectFromTable('List of Assets', 'cyk_asset',
41
- { 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' }
42
42
  )
43
43
  }
44
44
  catch (err) {
@@ -54,13 +54,16 @@ class AssetList extends Cmd {
54
54
  interface FileDescriptor {
55
55
  path: string
56
56
  mtime: Date
57
+ id?: number
57
58
  }
58
59
  class AssetUpload extends Cmd {
59
60
 
60
61
  constructor(name: string, description: string) {
61
62
  super(name)
62
63
  this.description(description)
63
- .option('-d --dest <destination>', 'route of destination')
64
+ .option('-a --auth <auth_schema>', 'authentication schema : basic | token | any, default is no authentication')
65
+ .option('-d --dest <destination>', 'destination path, directory name')
66
+ .option('-c --clean', 'clean destination path before uploading')
64
67
  .option('-y --yes', 'upload list is automatically confirmed')
65
68
  .argument('[sources...]', 'local files or directories to upload as assets to the server')
66
69
  .action(async (sources: any, options: any) => {
@@ -87,11 +90,21 @@ class AssetUpload extends Cmd {
87
90
 
88
91
  if (sources.length === 0) throw 'no source to upload'
89
92
 
93
+ if ( options.auth && ' basic | token | any '.indexOf(options.auth) === -1 ) {
94
+ throw 'valid authentication schemas are : basic | token | any'
95
+ }
96
+ logger.debug('options : ', options)
97
+ logger.debug('auth : ' + options.auth)
98
+
90
99
  let dest = "/"
91
100
  if (options.dest !== undefined) dest = options.dest
92
101
  if (dest.substring(0, 1) !== '/') dest = '/' + dest
93
102
  if (dest.substring(dest.length - 1) !== '/') dest = dest + '/'
94
103
 
104
+ if (options.clean) {
105
+ await this.cleanDestination(dest)
106
+ }
107
+
95
108
  for (let ind = 0; ind < sources.length; ind++) {
96
109
  const source = sources[ind]
97
110
  if (fs.existsSync(source) === false) throw 'source ' + source + ' does not exist'
@@ -102,7 +115,7 @@ class AssetUpload extends Cmd {
102
115
  else if (filestat.isFile() === true) {
103
116
  const base = path.parse(source).base
104
117
  logger.debug('upload file ' + source + ' to ' + dest + base)
105
- await this.uploadAsset({ path: source, mtime: filestat.mtime }, dest + base)
118
+ await this.uploadAsset({ path: source, mtime: filestat.mtime }, dest + base, options.auth)
106
119
  }
107
120
  }
108
121
  }
@@ -111,6 +124,22 @@ class AssetUpload extends Cmd {
111
124
  }
112
125
  }
113
126
 
127
+ //----------------------------------------------------------------------------------------------
128
+ // cleanDestination
129
+ //----------------------------------------------------------------------------------------------
130
+
131
+ async cleanDestination(dest: string) {
132
+
133
+ const remoteList = await this.scanAssets()
134
+ for(let ind = 0; ind < remoteList.length; ind++) {
135
+ const fd = remoteList[ind]
136
+ if (fd.path.startsWith(dest)) {
137
+ const url = '/api/admin/assets/' + fd.id
138
+ await this.dbRemote?.apiServer.delete(url)
139
+ }
140
+ }
141
+ }
142
+
114
143
  //----------------------------------------------------------------------------------------------
115
144
  // uploadDirectory
116
145
  //----------------------------------------------------------------------------------------------
@@ -131,8 +160,7 @@ class AssetUpload extends Cmd {
131
160
 
132
161
  this.scanDir(dirName, localList)
133
162
 
134
- const remoteList: FileDescriptor[] = []
135
- await this.scanAssets(remoteList)
163
+ const remoteList = await this.scanAssets()
136
164
 
137
165
  const uploadList = this.buildUploadList(dirName, dest, localList, remoteList)
138
166
 
@@ -147,7 +175,7 @@ class AssetUpload extends Cmd {
147
175
  }
148
176
 
149
177
  if (uploadConfirmed === true) {
150
- await this.uploadFiles(dirName, uploadList, dest)
178
+ await this.uploadFiles(dirName, uploadList, dest, options.auth)
151
179
  }
152
180
 
153
181
  // const rl = readline.createInterface(process.stdin, process.stdout)
@@ -193,8 +221,8 @@ class AssetUpload extends Cmd {
193
221
  // scanAssets
194
222
  //----------------------------------------------------------------------------------------------
195
223
 
196
- async scanAssets(result: FileDescriptor[]) {
197
-
224
+ async scanAssets() {
225
+ const result: FileDescriptor[] = []
198
226
  if (this.dbManager === undefined) throw 'dbManager undefined'
199
227
  const dbReq = new DBExecuteRequest()
200
228
  dbReq.selectFromTable = 'cyk_asset'
@@ -208,11 +236,13 @@ class AssetUpload extends Cmd {
208
236
  for (let ind = 0; ind < rows.list.length; ind++) {
209
237
  const { variable: row } = rows.list[ind]
210
238
  const record = row.data as ObjectData
239
+ const asset_id = (record.variables.getData('asset_id') as PrimitiveData).value as number
211
240
  const asset_route = (record.variables.getData('asset_route') as PrimitiveData).value as string
212
- const asset_last_update = (record.variables.getData('asset_last_update') as PrimitiveData).value as Date
241
+ const asset_last_update = (record.variables.getData('asset_last_update') as PrimitiveData)?.value as Date
213
242
  // logger.debug('asset_route ' + asset_route,'asset_last_update ' + asset_last_update)
214
- result.push({ path: asset_route, mtime: asset_last_update })
243
+ result.push({ path: asset_route, mtime: asset_last_update, id: asset_id })
215
244
  }
245
+ return result
216
246
  }
217
247
 
218
248
  //----------------------------------------------------------------------------------------------
@@ -258,12 +288,12 @@ class AssetUpload extends Cmd {
258
288
  // uploadFiles
259
289
  //----------------------------------------------------------------------------------------------
260
290
 
261
- async uploadFiles(dirName: string, uploadList: FileDescriptor[], dest: string) {
291
+ async uploadFiles(dirName: string, uploadList: FileDescriptor[], dest: string, auth: string | undefined) {
262
292
  for (let ind = 0; ind < uploadList.length; ind++) {
263
293
  const upload = uploadList[ind]
264
294
  const route = dest + upload.path.substring(dirName.length)
265
295
  logger.debug('upload ' + upload.path + ' to ' + route)
266
- await this.uploadAsset(upload, route)
296
+ await this.uploadAsset(upload, route, auth)
267
297
  }
268
298
  }
269
299
 
@@ -271,8 +301,8 @@ class AssetUpload extends Cmd {
271
301
  // uploadAsset
272
302
  //----------------------------------------------------------------------------------------------
273
303
 
274
- async uploadAsset(upload: FileDescriptor, route: string) {
275
- logger.debug('uploadAsset ' + upload.path + ' to route ' + route + ' with mimetype ' + this.mimetypeLookup(upload.path))
304
+ async uploadAsset(upload: FileDescriptor, route: string, auth?: string) {
305
+ logger.debug('uploadAsset ' + upload.path + ' to route ' + route + ' with mimetype ' + this.mimetypeLookup(upload.path) + ', auth : ' + auth)
276
306
 
277
307
  try {
278
308
  let dbAsset: DBAsset | undefined = await this.dbManager?.dbAssetExist(route)
@@ -283,7 +313,8 @@ class AssetUpload extends Cmd {
283
313
  if (mimetype === false) throw 'mimetype false for ' + upload
284
314
  dbAsset.mimetype = mimetype
285
315
  dbAsset.route = route
286
-
316
+ dbAsset.auth = auth
317
+
287
318
  // const fstat = fs.statSync(fileName)
288
319
  dbAsset.last_update = upload.mtime
289
320
 
@@ -318,7 +349,7 @@ class AssetUpload extends Cmd {
318
349
  const form = new FormData()
319
350
  form.append('uploadFile', file)
320
351
 
321
- const route = '/upload/cyk_asset/asset_content?asset_id=' + dbAsset.id
352
+ const route = '/api/upload/cyk_asset/asset_content?asset_id=' + dbAsset.id
322
353
  const resp = await this.dbRemote?.apiServer.post(route, form)
323
354
  if (resp.status === 200) {
324
355
  logger.info(fileName + ' uploaded')
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,27 +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
-
20
- try {
21
- const dotenvOutput = dotenv.config({path: options.env})
22
- if (dotenvOutput.error !== undefined) throw dotenvOutput.error
23
-
24
- const structure = new Structure()
25
- if (process.env.DBREMOTE_URL === undefined) throw 'DBREMOTE_URL undefined'
26
- logger.debug('Cmd.DBREMOTE_URL ' + process.env.DBREMOTE_URL)
27
- const nodeCrypto = new NodeCrypto()
28
- this.dbRemote = new DBRemote(structure.scope, process.env.DBREMOTE_URL, nodeCrypto)
29
- const login = await this.dbRemote.signin(process.env.USER_NAME, undefined, process.env.USER_PASSWORD)
30
- // logger.debug(login)
31
-
32
- this.dbManager = new DBManager(structure.scope, this.dbRemote)
33
- await this.dbManager.initialize()
34
- }
35
- catch (err) {
36
- logger.error(err)
37
- }
17
+
18
+ async prologue(options: any): Promise<SigninResponse> {
19
+
20
+ const dotenvOutput = dotenv.config({ path: options.env })
21
+ if (dotenvOutput.error !== undefined) throw dotenvOutput.error
22
+
23
+ const structure = new Structure()
24
+ if (process.env.DBREMOTE_URL === undefined) throw 'DBREMOTE_URL undefined'
25
+ logger.debug('Cmd.DBREMOTE_URL ' + process.env.DBREMOTE_URL)
26
+ const nodeCrypto = new NodeCrypto()
27
+ this.dbRemote = new DBRemote(structure.scope, process.env.DBREMOTE_URL, nodeCrypto)
28
+ const login = await this.dbRemote.signin(process.env.USER_NAME, undefined, process.env.USER_PASSWORD)
29
+ // logger.debug(login)
30
+
31
+ this.dbManager = new DBManager(structure.scope, this.dbRemote)
32
+ await this.dbManager.initialize()
33
+
34
+ return login
35
+
38
36
 
39
37
  }
40
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
 
@@ -232,6 +236,10 @@ class List {
232
236
  else {
233
237
  result = value.toString()
234
238
  }
239
+
240
+ // replace \n with a space
241
+ result = result.replace(/\n/, ' ')
242
+
235
243
  if (width !== undefined && width !== 0) {
236
244
  if (result.length >= width) {
237
245
  result = result.substring(0, width)
@@ -37,7 +37,7 @@ function getModuleDBName(filePath: string): string {
37
37
  // result = path.basename(filePath, '.xml')
38
38
 
39
39
  const result = path.parse(filePath).name
40
- const identifierRegex = /^[_a-zA-Z][_a-zA-Z0-9]*$/
40
+ const identifierRegex = /^[_a-zA-Z][-_a-zA-Z0-9]*$/
41
41
  if (result.match(identifierRegex) === null) throw 'filename ' + result + ' does not match identifier syntax'
42
42
  return result
43
43
  }
@@ -185,7 +185,7 @@ class ModuleList extends Cmd {
185
185
 
186
186
  const dbClient = new DBClient(this.dbManager)
187
187
  dbClient.selectFromTable('List of Modules', 'cyk_module',
188
- { 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' })
189
189
 
190
190
  }
191
191
  catch (err) {
@@ -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
  }
package/src/RunCommand.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Structure, Script, XmlError, DBRemote, DBManager, ModuleInstruction, parseXML } from "@cyklang/core"
1
+ import { Structure, Script, XmlError, DBRemote, DBManager, ModuleInstruction, parseXML, MapData } from "@cyklang/core"
2
2
  import * as fs from "fs"
3
3
  import { errorconsole, PrintInstructionType } from "./console"
4
4
  import loglevel from 'loglevel'
@@ -11,15 +11,15 @@ export class RunCommand extends Cmd {
11
11
  constructor() {
12
12
  super('run')
13
13
  this.description('run module').version('0.2')
14
- .argument('<files...>', 'local module file(s) to run')
15
- .action(async(files: any, options: any) => {
16
- await this.runFiles(files, options)
17
- })
14
+ .argument('<files...>', 'local module file(s) to run')
15
+ .action(async (files: any, options: any) => {
16
+ await this.runFiles(files, options)
17
+ })
18
18
  }
19
19
  async runFiles(files: string[], options: any) {
20
20
  try {
21
21
  await this.prologue(options)
22
- for (let ind=0; ind < files.length; ind++) {
22
+ for (let ind = 0; ind < files.length; ind++) {
23
23
  const result = await runFile(files[ind])
24
24
  // if (result === false) {
25
25
  // logger.debug('*********** FAILURE ' + process.argv[ind] + ' ***************')
@@ -40,32 +40,46 @@ async function runFile(filename: string): Promise<void> {
40
40
  filename = filename.substring(0, filename.indexOf("."))
41
41
  }
42
42
 
43
+ // skip filename with double underscore
44
+ if (filename.indexOf("__") !== -1) return
45
+
43
46
  let xmlfilename = filename + ".xml"
44
- // let logfilename = filename + ".log"
45
- // let outfilename = filename + ".output"
46
47
 
47
48
  let xml = fs.readFileSync(xmlfilename)
48
-
49
- // fs.writeFileSync(logfilename, "")
50
49
 
51
50
  try {
52
51
  if (process.env.DBREMOTE_URL === undefined) throw 'DBREMOTE_URL undefined'
53
- logger.trace('DBREMOTE_URL '+process.env.DBREMOTE_URL)
52
+ logger.trace('DBREMOTE_URL ' + process.env.DBREMOTE_URL)
54
53
  const structure = new Structure()
55
54
  const nodeCrypto = new NodeCrypto()
56
55
  const dbRemote = new DBRemote(structure.scope, process.env.DBREMOTE_URL, nodeCrypto)
57
56
  const login = await dbRemote.signin(process.env.USER_NAME, undefined, process.env.USER_PASSWORD)
58
57
  const dbManager = new DBManager(structure.scope, dbRemote)
59
58
  await dbManager.initialize()
60
- const tag = parseXML(xmlfilename, xml.toString())
61
- const moduleInstruction = new ModuleInstruction(tag, dbManager)
62
- await moduleInstruction.parse(structure.scope)
63
- await moduleInstruction.execute(structure.scope)
64
59
 
65
- // structure.scope.addInstructionType(new PrintInstructionType(logfilename))
66
- // let script = new Script(structure.scope, xmlfilename, xml.toString())
67
- // await script.parseInstructions()
68
- // await script.execute()
60
+ const user_lang = login.content.user_lang
61
+ if (user_lang && user_lang.trim() !== '') {
62
+
63
+ const langfilename = filename + "__" + user_lang + ".xml"
64
+
65
+ if (fs.existsSync(langfilename)) {
66
+ const langXml = fs.readFileSync(langfilename)
67
+ const tag = parseXML(xmlfilename, langXml.toString())
68
+ const modLang = new ModuleInstruction(tag, dbManager)
69
+ await modLang.parse(structure.scope)
70
+ await modLang.execute(structure.scope)
71
+
72
+ const langMap = modLang.objectData?.variables.getData(user_lang)
73
+
74
+ if (langMap !== null && langMap !== undefined) {
75
+ structure.mapLang = langMap as MapData
76
+ }
77
+ }
78
+ }
79
+
80
+ let script = new Script(structure.scope, xmlfilename, xml.toString())
81
+ await script.parseInstructions()
82
+ await script.execute()
69
83
  }
70
84
  catch (err) {
71
85
 
@@ -75,24 +89,4 @@ async function runFile(filename: string): Promise<void> {
75
89
  }
76
90
  console.log(err)
77
91
  }
78
-
79
- // let log = fs.readFileSync(logfilename)
80
- // if (fs.existsSync(outfilename) === true ) {
81
- // let out = fs.readFileSync(outfilename)
82
-
83
- // if (log.toString() === out.toString()) {
84
- // console.log("test " + xmlfilename + " SUCCESS")
85
- // result = true
86
- // }
87
- // else {
88
- // console.log("test " + xmlfilename + " FAILURE")
89
- // result = false
90
- // }
91
- // }
92
- // else {
93
- // console.log("test " + xmlfilename + " output file not found ")
94
- // result = false
95
- // }
96
-
97
- // return result
98
92
  }
@@ -20,8 +20,8 @@ export class TableCommand extends Command {
20
20
  this.addCommand(new TableImportCmd())
21
21
  this.addCommand(new TableList('list', 'list database tables'))
22
22
  this.addCommand(new TableList('l', '(l)ist database tables'))
23
- this.addCommand(new TableQuery('query', 'query select table content'))
24
- this.addCommand(new TableQuery('q', 'query select table content'))
23
+ this.addCommand(new TableData('data', 'table (d)ata'))
24
+ this.addCommand(new TableData('d', 'table (d)ata'))
25
25
  }
26
26
  }
27
27
 
@@ -273,30 +273,30 @@ class TableList extends Cmd {
273
273
 
274
274
  const dbClient = new DBClient(this.dbManager)
275
275
  dbClient.selectFromTable('List of Tables', 'cyk_table',
276
- { fields: 'table_id,table_name,table_description,table_access', sort: options.sort || '1' }
276
+ { fields: 'table_id,table_name,table_auth,table_access,table_description', sort: options.sort || '1' }
277
277
  )
278
278
  }
279
279
  }
280
280
 
281
281
  //--------------------------------------------------------------------------------------------------------------------
282
- // class TableQuery
282
+ // class TableData
283
283
  //--------------------------------------------------------------------------------------------------------------------
284
284
 
285
- class TableQuery extends Cmd {
285
+ class TableData extends Cmd {
286
286
 
287
287
  constructor(name: string, description: string) {
288
288
  super(name)
289
289
  this.description(description)
290
- .argument('<table>', 'table to query')
290
+ .argument('<table>', 'table name')
291
291
  .option('--where <clause_where_sql>', 'criteria in SQL syntax')
292
292
  .option('-s --sort <columns>', 'sort by columns positions (begins by 0) separated by comma')
293
293
  .option('-w --width <colwidth>', 'columns widths separated by comma')
294
294
  .action(async (table, options) => {
295
- this.commandQuery(table, options)
295
+ this.commandData(table, options)
296
296
  })
297
297
  }
298
298
 
299
- async commandQuery(table: string, options: any) {
299
+ async commandData(table: string, options: any) {
300
300
  try {
301
301
  await this.prologue(options)
302
302
  if (this.dbManager === undefined) throw 'dbManager undefined'
@@ -1,4 +1,4 @@
1
- import { Structure, Script, XmlError, DBRemote, DBManager } from "@cyklang/core"
1
+ import { Structure, Script, XmlError, DBRemote, DBManager, MapData, ModuleInstruction, parseXML } from "@cyklang/core"
2
2
  import * as fs from "fs"
3
3
  import { errorconsole, PrintInstructionType } from "./console"
4
4
  import loglevel from 'loglevel'
@@ -18,7 +18,7 @@ export class TestCommand extends Cmd {
18
18
  }
19
19
  async testRun(files: string[], options: any) {
20
20
  try {
21
- await this.prologue(options)
21
+ const signinResponse = await this.prologue(options)
22
22
  for (let ind=0; ind < files.length; ind++) {
23
23
  const result = await testfile(files[ind])
24
24
  if (result === false) {
@@ -41,6 +41,9 @@ async function testfile(filename: string): Promise<boolean> {
41
41
  filename = filename.substring(0, filename.indexOf("."))
42
42
  }
43
43
 
44
+ // skip filename with double underscore
45
+ if (filename.indexOf("__") !== -1) return true
46
+
44
47
  let xmlfilename = filename + ".xml"
45
48
  let logfilename = filename + ".log"
46
49
  let outfilename = filename + ".output"
@@ -62,6 +65,28 @@ async function testfile(filename: string): Promise<boolean> {
62
65
  await dbManager.initialize()
63
66
  structure.scope.addInstructionType(new PrintInstructionType(logfilename))
64
67
  let script = new Script(structure.scope, xmlfilename, xml.toString())
68
+ const user_lang = login.content.user_lang
69
+ if (user_lang && user_lang.trim() !== '') {
70
+
71
+ const langfilename = filename + "__" + user_lang + ".xml"
72
+
73
+ if (fs.existsSync(langfilename)) {
74
+ const langXml = fs.readFileSync(langfilename)
75
+ const tag = parseXML(xmlfilename, langXml.toString())
76
+ const modLang = new ModuleInstruction(tag, dbManager)
77
+ await modLang.parse(structure.scope)
78
+ await modLang.execute(structure.scope)
79
+
80
+ const langMap = modLang.objectData?.variables.getData(user_lang)
81
+
82
+ if (langMap !== null && langMap !== undefined) {
83
+ structure.mapLang = langMap as MapData
84
+
85
+ outfilename = filename + "__" + user_lang + ".output"
86
+ }
87
+ }
88
+ }
89
+
65
90
  await script.parseInstructions()
66
91
  await script.execute()
67
92
  // console.log(JSON.stringify(script.block.toString()))