@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/build/AssetCommand.js +63 -23
- package/build/Cmd.d.ts +2 -2
- package/build/Cmd.js +2 -1
- package/build/DBClient.d.ts +2 -0
- package/build/DBClient.js +16 -0
- package/build/ModuleCommand.js +11 -3
- package/build/QueryCommand.js +49 -39
- package/build/RunCommand.js +21 -28
- package/build/TableCommand.js +8 -8
- package/build/TestCommand.js +21 -2
- package/build/UserCommand.js +7 -1
- package/docker.env +2 -2
- package/package.json +3 -5
- package/src/AssetCommand.ts +82 -35
- package/src/Cmd.ts +10 -6
- package/src/DBClient.ts +24 -0
- package/src/ModuleCommand.ts +17 -11
- package/src/QueryCommand.ts +56 -39
- package/src/RunCommand.ts +33 -39
- package/src/TableCommand.ts +8 -8
- package/src/TestCommand.ts +28 -3
- package/src/UserCommand.ts +7 -1
- package/test/cyklang.xsd +870 -219
- package/test/t0.output +1 -1
- package/test/t0.xml +1 -1
- package/test/t01.output +16 -2
- package/test/t01.xml +46 -8
- package/test/t09.output +1 -1
- package/test/t09.xml +1 -1
- package/test/t0__us.output +4 -0
- package/test/t0__us.xml +7 -0
- package/test/t1.ts +8 -0
- package/test/t17.output +2 -0
- package/test/t17.xml +3 -1
- package/test/t20.output +0 -0
- package/test/t20.xml +17 -1
- package/test/t21.output +2 -0
- package/test/t21.xml +39 -9
- package/test/t22.output +0 -0
- package/test/t23.output +4 -0
- package/test/t23.xml +4 -4
- package/test/t24.output +1007 -0
- package/test/t24.xml +20 -0
- package/test/t25.output +4 -0
- package/test/t25.xml +23 -0
- package/test/t26.output +5 -0
- package/test/t26.xml +35 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyklang/cli",
|
|
3
|
-
"version": "0.
|
|
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.
|
|
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"
|
package/src/AssetCommand.ts
CHANGED
|
@@ -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
|
|
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,
|
|
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>', '
|
|
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('
|
|
152
|
+
logger.debug('options', options)
|
|
118
153
|
|
|
119
154
|
this.scanDir(dirName, localList)
|
|
120
155
|
|
|
121
|
-
const remoteList
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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(
|
|
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)
|
|
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 (
|
|
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 ' +
|
|
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 =
|
|
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 (
|
|
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
|
-
|
|
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)
|
package/src/ModuleCommand.ts
CHANGED
|
@@ -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
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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
|
|
package/src/QueryCommand.ts
CHANGED
|
@@ -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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
}
|