@cyklang/cli 0.1.2 → 0.2.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.d.ts +4 -0
- package/build/AssetCommand.js +293 -0
- package/build/Cmd.d.ts +2 -1
- package/build/Cmd.js +3 -3
- package/build/DBClient.d.ts +1 -0
- package/build/DBClient.js +51 -17
- package/build/ModuleCommand.js +6 -6
- package/build/TableCommand.js +235 -45
- package/build/index.js +3 -0
- package/package.json +5 -2
- package/pgdata/entry.csv +22 -0
- package/pgdata/setting.csv +4 -0
- package/src/AssetCommand.ts +307 -0
- package/src/Cmd.ts +4 -3
- package/src/DBClient.ts +70 -31
- package/src/ModuleCommand.ts +7 -5
- package/src/TableCommand.ts +269 -56
- package/src/index.ts +3 -0
- package/test/cyklang.xsd +439 -0
- package/test/t0.output +4 -0
- package/test/t0.xml +26 -0
- package/test/t01.output +32 -0
- package/test/t01.xml +185 -0
- package/test/t02.output +10 -0
- package/test/t02.xml +88 -0
- package/test/t03.output +9 -0
- package/test/t03.xml +74 -0
- package/test/t04.output +29 -0
- package/test/t04.xml +116 -0
- package/test/t05.output +18 -0
- package/test/t05.xml +41 -0
- package/test/t06.output +4 -0
- package/test/t06.xml +16 -0
- package/test/t07.output +5 -0
- package/test/t07.xml +82 -0
- package/test/t08.output +8 -0
- package/test/t08.xml +57 -0
- package/test/t09.output +10 -0
- package/test/t09.xml +29 -0
- package/test/t10.xml +125 -0
- package/test/t11.output +3 -0
- package/test/t11.xml +25 -0
- package/test/t12.output +7 -0
- package/test/t12.xml +42 -0
- package/test/t13.xml +23 -0
- package/test/t14.output +50 -0
- package/test/t14.xml +82 -0
- package/test/t14.xsd +102 -0
- package/test/t15.xml +47 -0
- package/test/t16.output +49 -0
- package/test/t16.xml +86 -0
- package/test/t17.output +5 -0
- package/test/t17.xml +21 -0
- package/test/t18.output +22 -0
- package/test/t18.xml +59 -0
- package/test/t19.xml +234 -0
- package/test/t20.xml +15 -0
- package/test/t21.output +21 -0
- package/test/t21.xml +71 -0
- package/test/t22.xml +23 -0
- package/test/t23.xml +44 -0
- package/test/t24.xml +10 -0
- package/test/test.json +113 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.AssetCommand = void 0;
|
|
26
|
+
const commander_1 = require("commander");
|
|
27
|
+
const loglevel_1 = require("loglevel");
|
|
28
|
+
const Cmd_1 = require("./Cmd");
|
|
29
|
+
const DBClient_1 = require("./DBClient");
|
|
30
|
+
const fs = __importStar(require("fs"));
|
|
31
|
+
const path_1 = __importDefault(require("path"));
|
|
32
|
+
const mime_types_1 = __importDefault(require("mime-types"));
|
|
33
|
+
const readline_1 = __importDefault(require("readline"));
|
|
34
|
+
const core_1 = require("@cyklang/core");
|
|
35
|
+
const form_data_1 = __importDefault(require("form-data"));
|
|
36
|
+
const logger = (0, loglevel_1.getLogger)('AssetCommand.ts');
|
|
37
|
+
logger.setLevel('debug');
|
|
38
|
+
class AssetCommand extends commander_1.Command {
|
|
39
|
+
constructor(name, description) {
|
|
40
|
+
super(name);
|
|
41
|
+
this.description(description);
|
|
42
|
+
this.addCommand(new AssetList('list', 'list assets'));
|
|
43
|
+
this.addCommand(new AssetList('l', '(l)ist assets'));
|
|
44
|
+
this.addCommand(new AssetUpload('upload', 'upload assets from current directory'));
|
|
45
|
+
this.addCommand(new AssetUpload('u', '(u)pload assets'));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.AssetCommand = AssetCommand;
|
|
49
|
+
class AssetList extends Cmd_1.Cmd {
|
|
50
|
+
constructor(name, description) {
|
|
51
|
+
super(name);
|
|
52
|
+
this.description(description)
|
|
53
|
+
.option('-s --sort <columns>', 'sort list by column numbers (begins by 0) separated by comma')
|
|
54
|
+
.action(async (options) => { await this.commandList(options); });
|
|
55
|
+
}
|
|
56
|
+
async commandList(options) {
|
|
57
|
+
try {
|
|
58
|
+
await this.prologue(options);
|
|
59
|
+
if (this.dbManager === undefined)
|
|
60
|
+
throw 'dbManager undefined';
|
|
61
|
+
const dbClient = new DBClient_1.DBClient(this.dbManager);
|
|
62
|
+
dbClient.selectFromTable('List of Assets', 'cyk_asset', { fields: 'asset_id,asset_route,asset_last_update,asset_mimetype', sort: options.sort || '1' });
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
logger.error(err);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
class AssetUpload extends Cmd_1.Cmd {
|
|
70
|
+
constructor(name, description) {
|
|
71
|
+
super(name);
|
|
72
|
+
//----------------------------------------------------------------------------------------------
|
|
73
|
+
// file2exclude
|
|
74
|
+
//----------------------------------------------------------------------------------------------
|
|
75
|
+
this.ignorePatterns = ['.git', 'node_modules'];
|
|
76
|
+
this.description(description)
|
|
77
|
+
.option('-d --dest <destination>', 'route of destination')
|
|
78
|
+
.argument('[sources...]', 'local files or directories to upload as assets to the server')
|
|
79
|
+
.action(async (sources, options) => {
|
|
80
|
+
await this.commandUpload(sources, options);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
async commandUpload(sources, options) {
|
|
84
|
+
try {
|
|
85
|
+
await this.prologue(options);
|
|
86
|
+
if (this.dbManager === undefined)
|
|
87
|
+
throw 'dbManager undefined';
|
|
88
|
+
if (sources.length === 0)
|
|
89
|
+
throw 'no source to upload';
|
|
90
|
+
let dest = "/";
|
|
91
|
+
if (options.dest !== undefined)
|
|
92
|
+
dest = options.dest;
|
|
93
|
+
if (dest.substring(0, 1) !== '/')
|
|
94
|
+
dest = '/' + dest;
|
|
95
|
+
if (dest.substring(dest.length - 1) !== '/')
|
|
96
|
+
dest = dest + '/';
|
|
97
|
+
for (let ind = 0; ind < sources.length; ind++) {
|
|
98
|
+
const source = sources[ind];
|
|
99
|
+
if (fs.existsSync(source) === false)
|
|
100
|
+
throw 'source ' + source + ' does not exist';
|
|
101
|
+
const filestat = fs.lstatSync(source);
|
|
102
|
+
if (filestat.isDirectory() === true) {
|
|
103
|
+
await this.uploadDirectory(source, dest);
|
|
104
|
+
}
|
|
105
|
+
else if (filestat.isFile() === true) {
|
|
106
|
+
const base = path_1.default.parse(source).base;
|
|
107
|
+
logger.debug('upload file ' + source + ' to ' + dest + base);
|
|
108
|
+
await this.uploadAsset({ path: source, mtime: filestat.mtime }, dest + base);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
logger.error(err);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//----------------------------------------------------------------------------------------------
|
|
117
|
+
// uploadDirectory
|
|
118
|
+
//----------------------------------------------------------------------------------------------
|
|
119
|
+
async uploadDirectory(source, dest) {
|
|
120
|
+
const localList = [];
|
|
121
|
+
let dirName;
|
|
122
|
+
if (source.substring(source.length - 1) === '/') {
|
|
123
|
+
// trailing directory separator
|
|
124
|
+
dirName = source;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
dirName = source + '/';
|
|
128
|
+
}
|
|
129
|
+
logger.debug('dirName', dirName);
|
|
130
|
+
this.scanDir(dirName, localList);
|
|
131
|
+
const remoteList = [];
|
|
132
|
+
await this.scanAssets(remoteList);
|
|
133
|
+
const uploadList = this.buildUploadList(dirName, dest, localList, remoteList);
|
|
134
|
+
// logger.info(fileNames.join('\n'))
|
|
135
|
+
if (uploadList.length === 0)
|
|
136
|
+
throw 'None file to upload';
|
|
137
|
+
const rl = readline_1.default.createInterface(process.stdin, process.stdout);
|
|
138
|
+
rl.question('Do you want to upload this(these) ' + uploadList.length + ' file(s) (Y/N/y/n) ?', async (reply) => {
|
|
139
|
+
rl.close();
|
|
140
|
+
if (reply !== 'Y' && reply !== 'y') {
|
|
141
|
+
logger.info('upload cancelled');
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
await this.uploadFiles(dirName, uploadList, dest);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
//----------------------------------------------------------------------------------------------
|
|
148
|
+
// buildUploadList
|
|
149
|
+
//----------------------------------------------------------------------------------------------
|
|
150
|
+
buildUploadList(dirName, dest, localList, remoteList) {
|
|
151
|
+
const result = [];
|
|
152
|
+
const remoteMap = new Map();
|
|
153
|
+
for (let ind = 0; ind < remoteList.length; ind++) {
|
|
154
|
+
const remote = remoteList[ind];
|
|
155
|
+
remoteMap.set(remote.path, remote);
|
|
156
|
+
}
|
|
157
|
+
for (let ind = 0; ind < localList.length; ind++) {
|
|
158
|
+
const localDesc = localList[ind];
|
|
159
|
+
const route = dest + localDesc.path.substring(dirName.length);
|
|
160
|
+
const remoteDesc = remoteMap.get(route);
|
|
161
|
+
if (remoteDesc === undefined || remoteDesc.mtime.getTime() + 1000 < localDesc.mtime.getTime()) {
|
|
162
|
+
if (remoteDesc === undefined)
|
|
163
|
+
logger.debug('remoteDesc undefined');
|
|
164
|
+
else
|
|
165
|
+
logger.debug('remoteDesc.mtime ' + remoteDesc.mtime.getTime(), 'localDesc.mtime ' + localDesc.mtime.getTime());
|
|
166
|
+
logger.info(localDesc.path);
|
|
167
|
+
result.push(localDesc);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
//----------------------------------------------------------------------------------------------
|
|
173
|
+
// scanAssets
|
|
174
|
+
//----------------------------------------------------------------------------------------------
|
|
175
|
+
async scanAssets(result) {
|
|
176
|
+
if (this.dbManager === undefined)
|
|
177
|
+
throw 'dbManager undefined';
|
|
178
|
+
const dbReq = new core_1.DBExecuteRequest();
|
|
179
|
+
dbReq.selectFromTable = 'cyk_asset';
|
|
180
|
+
const pFields = dbReq.parameters.addVariable('fields', this.dbManager.scope.structure.stringDataType);
|
|
181
|
+
pFields.data = new core_1.PrimitiveData(this.dbManager.scope.structure.stringDataType, "asset_id,asset_route,asset_last_update,asset_mimetype");
|
|
182
|
+
const xmlResult = await this.dbManager.dbExecute(dbReq);
|
|
183
|
+
if (xmlResult === undefined || xmlResult === null)
|
|
184
|
+
throw 'xmlResult null or undefined';
|
|
185
|
+
const tag = (0, core_1.parseXML)('scanAssets', xmlResult);
|
|
186
|
+
const objResult = await this.dbManager.scope.structure.objectDataType.parseData(tag, this.dbManager.scope);
|
|
187
|
+
const rows = objResult.variables.getData('cyk_asset').variables;
|
|
188
|
+
for (let ind = 0; ind < rows.list.length; ind++) {
|
|
189
|
+
const { variable: row } = rows.list[ind];
|
|
190
|
+
const record = row.data;
|
|
191
|
+
const asset_route = record.variables.getData('asset_route').value;
|
|
192
|
+
const asset_last_update = record.variables.getData('asset_last_update').value;
|
|
193
|
+
// logger.debug('asset_route ' + asset_route,'asset_last_update ' + asset_last_update)
|
|
194
|
+
result.push({ path: asset_route, mtime: asset_last_update });
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//----------------------------------------------------------------------------------------------
|
|
198
|
+
// scanDir
|
|
199
|
+
//----------------------------------------------------------------------------------------------
|
|
200
|
+
scanDir(dirName, result) {
|
|
201
|
+
const files = fs.readdirSync(dirName);
|
|
202
|
+
for (let ind = 0; ind < files.length; ind++) {
|
|
203
|
+
const fileName = files[ind];
|
|
204
|
+
if (this.file2exclude(fileName) === true)
|
|
205
|
+
continue;
|
|
206
|
+
const fstat = fs.statSync(dirName + fileName);
|
|
207
|
+
if (fstat.isDirectory() === true) {
|
|
208
|
+
this.scanDir(dirName + fileName + '/', result);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
if (mime_types_1.default.lookup(fileName) === false) {
|
|
212
|
+
logger.info(fileName + ' file extension is unknown and will not be uploaded');
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
//const dbAssetExist = this.dbManager?.dbAssetExist()
|
|
216
|
+
result.push({ path: dirName + fileName, mtime: fstat.mtime });
|
|
217
|
+
// logger.debug(dirName + '/' + fileName)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
file2exclude(fileName) {
|
|
222
|
+
let result = false;
|
|
223
|
+
this.ignorePatterns.forEach((pattern) => {
|
|
224
|
+
if (fileName === pattern)
|
|
225
|
+
result = true;
|
|
226
|
+
});
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
//----------------------------------------------------------------------------------------------
|
|
230
|
+
// uploadFiles
|
|
231
|
+
//----------------------------------------------------------------------------------------------
|
|
232
|
+
async uploadFiles(dirName, uploadList, dest) {
|
|
233
|
+
for (let ind = 0; ind < uploadList.length; ind++) {
|
|
234
|
+
const upload = uploadList[ind];
|
|
235
|
+
const route = dest + upload.path.substring(dirName.length);
|
|
236
|
+
logger.debug('upload ' + upload.path + ' to ' + route);
|
|
237
|
+
await this.uploadAsset(upload, route);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
//----------------------------------------------------------------------------------------------
|
|
241
|
+
// uploadAsset
|
|
242
|
+
//----------------------------------------------------------------------------------------------
|
|
243
|
+
async uploadAsset(upload, route) {
|
|
244
|
+
logger.debug('uploadAsset ' + upload.path + ' to route ' + route + ' with mimetype ' + mime_types_1.default.lookup(upload.path));
|
|
245
|
+
try {
|
|
246
|
+
let dbAsset = await this.dbManager?.dbAssetExist(route);
|
|
247
|
+
if (dbAsset === undefined) {
|
|
248
|
+
dbAsset = new core_1.DBAsset();
|
|
249
|
+
}
|
|
250
|
+
const mimetype = mime_types_1.default.lookup(upload.path);
|
|
251
|
+
if (mimetype === false)
|
|
252
|
+
throw 'mimetype false for ' + upload;
|
|
253
|
+
dbAsset.mimetype = mimetype;
|
|
254
|
+
dbAsset.route = route;
|
|
255
|
+
// const fstat = fs.statSync(fileName)
|
|
256
|
+
dbAsset.last_update = upload.mtime;
|
|
257
|
+
// const contentBuffer = fs.readFileSync(fileName)
|
|
258
|
+
// dbAsset.content = contentBuffer
|
|
259
|
+
// logger.debug('dbAsset.content length ' + dbAsset.content.length)
|
|
260
|
+
if (dbAsset.id === undefined) {
|
|
261
|
+
dbAsset.id = await this.dbManager?.dbAssetInsert(dbAsset);
|
|
262
|
+
logger.info('inserted asset ' + dbAsset.id + ' route ' + dbAsset.route);
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
await this.dbManager?.dbAssetUpdate(dbAsset);
|
|
266
|
+
logger.info('updated asset ' + dbAsset.route);
|
|
267
|
+
}
|
|
268
|
+
await this.uploadAssetContent(dbAsset, upload.path);
|
|
269
|
+
}
|
|
270
|
+
catch (err) {
|
|
271
|
+
logger.error(err);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
//----------------------------------------------------------------------------------------------
|
|
275
|
+
// uploadAssetContent
|
|
276
|
+
//----------------------------------------------------------------------------------------------
|
|
277
|
+
async uploadAssetContent(dbAsset, fileName) {
|
|
278
|
+
logger.debug('uploadAssetContent file ' + fileName + ' to path ' + path_1.default);
|
|
279
|
+
try {
|
|
280
|
+
const file = fs.createReadStream(fileName);
|
|
281
|
+
const form = new form_data_1.default();
|
|
282
|
+
form.append('uploadFile', file);
|
|
283
|
+
const route = '/upload/cyk_asset/asset_content?asset_id=' + dbAsset.id;
|
|
284
|
+
const resp = await this.dbRemote?.apiServer.post(route, form);
|
|
285
|
+
if (resp.status === 200) {
|
|
286
|
+
logger.info(fileName + ' uploaded');
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
logger.error(err);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
package/build/Cmd.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { DBManager } from "@cyklang/core";
|
|
1
|
+
import { DBManager, DBRemote } from "@cyklang/core";
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
export declare class Cmd extends Command {
|
|
4
4
|
dbManager: DBManager | undefined;
|
|
5
|
+
dbRemote: DBRemote | undefined;
|
|
5
6
|
constructor(name: string);
|
|
6
7
|
prologue(options: any): Promise<void>;
|
|
7
8
|
}
|
package/build/Cmd.js
CHANGED
|
@@ -25,10 +25,10 @@ class Cmd extends commander_1.Command {
|
|
|
25
25
|
throw 'DBREMOTE_URL undefined';
|
|
26
26
|
logger.debug('DBREMOTE_URL ' + process.env.DBREMOTE_URL);
|
|
27
27
|
const nodeCrypto = new NodeCrypto_1.NodeCrypto();
|
|
28
|
-
|
|
29
|
-
const login = await dbRemote.signin(process.env.USER_NAME, undefined, process.env.USER_PASSWORD);
|
|
28
|
+
this.dbRemote = new core_1.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
30
|
// logger.debug(login)
|
|
31
|
-
this.dbManager = new core_1.DBManager(structure.scope, dbRemote);
|
|
31
|
+
this.dbManager = new core_1.DBManager(structure.scope, this.dbRemote);
|
|
32
32
|
await this.dbManager.initialize();
|
|
33
33
|
}
|
|
34
34
|
}
|
package/build/DBClient.d.ts
CHANGED
package/build/DBClient.js
CHANGED
|
@@ -56,6 +56,8 @@ class DBClient {
|
|
|
56
56
|
const dbTable = new core_1.DBTable(tagDBTable);
|
|
57
57
|
const fields = options.fields.split(',');
|
|
58
58
|
const list = new List();
|
|
59
|
+
if (options.width !== undefined)
|
|
60
|
+
list.width = options.width;
|
|
59
61
|
for (let ind = 0; ind < fields.length; ind++) {
|
|
60
62
|
const field = fields[ind];
|
|
61
63
|
const dbColumn = dbTable.columns.filter((dbColumn) => dbColumn.name === field)[0];
|
|
@@ -78,6 +80,7 @@ class DBClient {
|
|
|
78
80
|
exports.DBClient = DBClient;
|
|
79
81
|
class List {
|
|
80
82
|
constructor() {
|
|
83
|
+
this.width = "0";
|
|
81
84
|
this.columns = [];
|
|
82
85
|
this.rows = [];
|
|
83
86
|
this.lines = [];
|
|
@@ -102,21 +105,40 @@ class List {
|
|
|
102
105
|
this.rows.push(new Row(cells));
|
|
103
106
|
}
|
|
104
107
|
renderList(title) {
|
|
105
|
-
//
|
|
108
|
+
// parse width option
|
|
109
|
+
const colws = [];
|
|
110
|
+
const colws_ = this.width.split(',');
|
|
111
|
+
for (let ind = 0; ind < colws_.length; ind++) {
|
|
112
|
+
const colw = Number.parseInt(colws_[ind]);
|
|
113
|
+
if (isNaN(colw)) {
|
|
114
|
+
const msg = '--width incorrect format : ' + this.width;
|
|
115
|
+
throw msg;
|
|
116
|
+
}
|
|
117
|
+
colws.push(colw);
|
|
118
|
+
}
|
|
119
|
+
logger.debug('colws', colws.join(','));
|
|
120
|
+
// calculate column.actualWidth
|
|
106
121
|
let total_width = 0;
|
|
107
122
|
for (let indi = 0; indi < this.columns.length; indi++) {
|
|
108
123
|
const column = this.columns[indi];
|
|
109
|
-
|
|
124
|
+
if (indi < colws.length)
|
|
125
|
+
column.width = colws[indi];
|
|
126
|
+
else
|
|
127
|
+
column.width = colws[colws.length - 1];
|
|
128
|
+
column.actualWidth = column.label.length;
|
|
110
129
|
this.rows.forEach((row) => {
|
|
111
130
|
const cell = row.cells[indi];
|
|
112
131
|
const renderedCell = this.renderCell(cell);
|
|
113
|
-
if (renderedCell.length > column.
|
|
114
|
-
column.width
|
|
132
|
+
if (renderedCell.length > column.actualWidth) {
|
|
133
|
+
if (column.width === 0 || renderedCell.length < column.width)
|
|
134
|
+
column.actualWidth = renderedCell.length;
|
|
135
|
+
else
|
|
136
|
+
column.actualWidth = column.width;
|
|
115
137
|
}
|
|
116
138
|
});
|
|
117
139
|
if (total_width > 0)
|
|
118
140
|
total_width += 3;
|
|
119
|
-
total_width += column.
|
|
141
|
+
total_width += column.actualWidth;
|
|
120
142
|
}
|
|
121
143
|
// title
|
|
122
144
|
this.lines.push(this.renderCell(title, total_width, 'center'));
|
|
@@ -128,6 +150,8 @@ class List {
|
|
|
128
150
|
const row = this.rows[indj];
|
|
129
151
|
this.lines.push(this.renderRow(row));
|
|
130
152
|
}
|
|
153
|
+
this.lines.push(this.renderSeparator());
|
|
154
|
+
this.lines.push('Number of lines : ' + this.rows.length);
|
|
131
155
|
return this.lines.join('\n');
|
|
132
156
|
}
|
|
133
157
|
renderHeaderRow() {
|
|
@@ -136,7 +160,7 @@ class List {
|
|
|
136
160
|
const column = this.columns[indi];
|
|
137
161
|
if (result !== '')
|
|
138
162
|
result += ' | ';
|
|
139
|
-
result += this.renderCell(column.label, column.
|
|
163
|
+
result += this.renderCell(column.label, column.actualWidth, 'center');
|
|
140
164
|
}
|
|
141
165
|
return result;
|
|
142
166
|
}
|
|
@@ -150,7 +174,7 @@ class List {
|
|
|
150
174
|
}
|
|
151
175
|
if (result !== '')
|
|
152
176
|
result += ' | ';
|
|
153
|
-
result += this.renderCell(row.cells[indi], column.
|
|
177
|
+
result += this.renderCell(row.cells[indi], column.actualWidth, justify);
|
|
154
178
|
}
|
|
155
179
|
return result;
|
|
156
180
|
}
|
|
@@ -160,7 +184,7 @@ class List {
|
|
|
160
184
|
const column = this.columns[indi];
|
|
161
185
|
if (result !== '')
|
|
162
186
|
result += '-+-';
|
|
163
|
-
result += '-'.repeat(column.
|
|
187
|
+
result += '-'.repeat(column.actualWidth);
|
|
164
188
|
}
|
|
165
189
|
return result;
|
|
166
190
|
}
|
|
@@ -172,20 +196,29 @@ class List {
|
|
|
172
196
|
else if (value === null) {
|
|
173
197
|
result = 'null';
|
|
174
198
|
}
|
|
199
|
+
else if (value instanceof Date) {
|
|
200
|
+
const d = value;
|
|
201
|
+
result = d.toISOString();
|
|
202
|
+
}
|
|
175
203
|
else {
|
|
176
204
|
result = value.toString();
|
|
177
205
|
}
|
|
178
|
-
if (width !== undefined &&
|
|
179
|
-
if (
|
|
180
|
-
result
|
|
181
|
-
}
|
|
182
|
-
else if (justify === 'right') {
|
|
183
|
-
result = ' '.repeat(width - result.length) + result;
|
|
206
|
+
if (width !== undefined && width !== 0) {
|
|
207
|
+
if (result.length >= width) {
|
|
208
|
+
result = result.substring(0, width);
|
|
184
209
|
}
|
|
185
210
|
else {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
211
|
+
if (justify === undefined || justify === 'left') {
|
|
212
|
+
result += ' '.repeat(width - result.length);
|
|
213
|
+
}
|
|
214
|
+
else if (justify === 'right') {
|
|
215
|
+
result = ' '.repeat(width - result.length) + result;
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
// justify === center
|
|
219
|
+
const before = Math.floor((width - result.length) / 2);
|
|
220
|
+
result = ' '.repeat(before) + result + ' '.repeat(width - result.length - before);
|
|
221
|
+
}
|
|
189
222
|
}
|
|
190
223
|
}
|
|
191
224
|
return result;
|
|
@@ -195,6 +228,7 @@ class Column {
|
|
|
195
228
|
constructor(name) {
|
|
196
229
|
this.label = '';
|
|
197
230
|
this.width = 0;
|
|
231
|
+
this.actualWidth = 0;
|
|
198
232
|
this.name = name;
|
|
199
233
|
}
|
|
200
234
|
}
|
package/build/ModuleCommand.js
CHANGED
|
@@ -53,10 +53,10 @@ Otherwise, a new module is inserted in the database. To rename a module, use opt
|
|
|
53
53
|
}
|
|
54
54
|
exports.ModuleCommand = ModuleCommand;
|
|
55
55
|
function getModuleDBName(filePath) {
|
|
56
|
-
let result
|
|
57
|
-
if (filePath.endsWith('.xml') === false)
|
|
58
|
-
|
|
59
|
-
result = path_1.default.
|
|
56
|
+
// let result
|
|
57
|
+
// if (filePath.endsWith('.xml') === false) throw filePath + ' does not have .xml extension'
|
|
58
|
+
// result = path.basename(filePath, '.xml')
|
|
59
|
+
const result = path_1.default.parse(filePath).name;
|
|
60
60
|
const identifierRegex = /^[_a-zA-Z][_a-zA-Z0-9]*$/;
|
|
61
61
|
if (result.match(identifierRegex) === null)
|
|
62
62
|
throw 'filename ' + result + ' does not match identifier syntax';
|
|
@@ -66,7 +66,7 @@ class ModuleUpload extends Cmd_1.Cmd {
|
|
|
66
66
|
constructor(name, description) {
|
|
67
67
|
super(name);
|
|
68
68
|
this.description(description)
|
|
69
|
-
.option('-i --id <id>', 'module ID to
|
|
69
|
+
.option('-i --id <id>', 'module ID to upload')
|
|
70
70
|
.argument('[files...]', 'local module file(s) to upload to the server')
|
|
71
71
|
.action(async (files, options) => {
|
|
72
72
|
await this.commandUpload(files, options);
|
|
@@ -171,7 +171,7 @@ class ModuleDownload extends Cmd_1.Cmd {
|
|
|
171
171
|
}
|
|
172
172
|
const filePath = dbname + '.xml';
|
|
173
173
|
if (fs.existsSync(filePath) === true) {
|
|
174
|
-
logger.info('file ' + filePath + ' already exists
|
|
174
|
+
logger.info('file ' + filePath + ' already exists. Remove it before launching the command if you want to overwrite.');
|
|
175
175
|
}
|
|
176
176
|
else {
|
|
177
177
|
fs.writeFileSync(filePath, dbModule.source || '');
|