Socket
Socket
Sign inDemoInstall

@cyklang/cli

Package Overview
Dependencies
17
Maintainers
1
Versions
59
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.2 to 0.2.0

build/AssetCommand.d.ts

3

build/Cmd.d.ts

@@ -1,7 +0,8 @@

import { DBManager } from "@cyklang/core";
import { DBManager, DBRemote } from "@cyklang/core";
import { Command } from "commander";
export declare class Cmd extends Command {
dbManager: DBManager | undefined;
dbRemote: DBRemote | undefined;
constructor(name: string);
prologue(options: any): Promise<void>;
}

@@ -28,6 +28,6 @@ "use strict";

const nodeCrypto = new NodeCrypto_1.NodeCrypto();
const dbRemote = new core_1.DBRemote(structure.scope, process.env.DBREMOTE_URL, nodeCrypto);
const login = await dbRemote.signin(process.env.USER_NAME, undefined, process.env.USER_PASSWORD);
this.dbRemote = new core_1.DBRemote(structure.scope, process.env.DBREMOTE_URL, nodeCrypto);
const login = await this.dbRemote.signin(process.env.USER_NAME, undefined, process.env.USER_PASSWORD);
// logger.debug(login)
this.dbManager = new core_1.DBManager(structure.scope, dbRemote);
this.dbManager = new core_1.DBManager(structure.scope, this.dbRemote);
await this.dbManager.initialize();

@@ -34,0 +34,0 @@ }

@@ -9,3 +9,4 @@ import { DBManager } from "@cyklang/core";

where?: string | undefined;
width?: string | undefined;
}): Promise<void>;
}

@@ -59,2 +59,4 @@ "use strict";

const list = new List();
if (options.width !== undefined)
list.width = options.width;
for (let ind = 0; ind < fields.length; ind++) {

@@ -82,2 +84,3 @@ const field = fields[ind];

constructor() {
this.width = "0";
this.columns = [];

@@ -107,12 +110,31 @@ this.rows = [];

renderList(title) {
// calculate column.width
// parse width option
const colws = [];
const colws_ = this.width.split(',');
for (let ind = 0; ind < colws_.length; ind++) {
const colw = Number.parseInt(colws_[ind]);
if (isNaN(colw)) {
const msg = '--width incorrect format : ' + this.width;
throw msg;
}
colws.push(colw);
}
logger.debug('colws', colws.join(','));
// calculate column.actualWidth
let total_width = 0;
for (let indi = 0; indi < this.columns.length; indi++) {
const column = this.columns[indi];
column.width = column.label.length;
if (indi < colws.length)
column.width = colws[indi];
else
column.width = colws[colws.length - 1];
column.actualWidth = column.label.length;
this.rows.forEach((row) => {
const cell = row.cells[indi];
const renderedCell = this.renderCell(cell);
if (renderedCell.length > column.width) {
column.width = renderedCell.length;
if (renderedCell.length > column.actualWidth) {
if (column.width === 0 || renderedCell.length < column.width)
column.actualWidth = renderedCell.length;
else
column.actualWidth = column.width;
}

@@ -122,3 +144,3 @@ });

total_width += 3;
total_width += column.width;
total_width += column.actualWidth;
}

@@ -135,2 +157,4 @@ // title

}
this.lines.push(this.renderSeparator());
this.lines.push('Number of lines : ' + this.rows.length);
return this.lines.join('\n');

@@ -144,3 +168,3 @@ }

result += ' | ';
result += this.renderCell(column.label, column.width, 'center');
result += this.renderCell(column.label, column.actualWidth, 'center');
}

@@ -159,3 +183,3 @@ return result;

result += ' | ';
result += this.renderCell(row.cells[indi], column.width, justify);
result += this.renderCell(row.cells[indi], column.actualWidth, justify);
}

@@ -170,3 +194,3 @@ return result;

result += '-+-';
result += '-'.repeat(column.width);
result += '-'.repeat(column.actualWidth);
}

@@ -183,16 +207,25 @@ return result;

}
else if (value instanceof Date) {
const d = value;
result = d.toISOString();
}
else {
result = value.toString();
}
if (width !== undefined && result.length < width) {
if (justify === undefined || justify === 'left') {
result += ' '.repeat(width - result.length);
if (width !== undefined && width !== 0) {
if (result.length >= width) {
result = result.substring(0, width);
}
else if (justify === 'right') {
result = ' '.repeat(width - result.length) + result;
}
else {
// justify === center
const before = Math.floor((width - result.length) / 2);
result = ' '.repeat(before) + result + ' '.repeat(width - result.length - before);
if (justify === undefined || justify === 'left') {
result += ' '.repeat(width - result.length);
}
else if (justify === 'right') {
result = ' '.repeat(width - result.length) + result;
}
else {
// justify === center
const before = Math.floor((width - result.length) / 2);
result = ' '.repeat(before) + result + ' '.repeat(width - result.length - before);
}
}

@@ -207,2 +240,3 @@ }

this.width = 0;
this.actualWidth = 0;
this.name = name;

@@ -209,0 +243,0 @@ }

@@ -16,2 +16,3 @@ #!/usr/bin/env node

const InitCommand_1 = require("./InitCommand");
const AssetCommand_1 = require("./AssetCommand");
const logger = loglevel_1.default.getLogger("index.ts");

@@ -23,2 +24,4 @@ logger.setLevel("debug");

program.addCommand(new InitCommand_1.InitCommand('init'));
program.addCommand(new AssetCommand_1.AssetCommand('asset', 'manage assets'));
program.addCommand(new AssetCommand_1.AssetCommand('a', 'manage assets'));
program.addCommand(new ModuleCommand_1.ModuleCommand('module'));

@@ -25,0 +28,0 @@ program.addCommand(new ModuleCommand_1.ModuleCommand('m'));

@@ -56,6 +56,6 @@ #!/usr/bin/env ts-node

function getModuleDBName(filePath) {
let result;
if (filePath.endsWith('.xml') === false)
throw filePath + ' does not have .xml extension';
result = path_1.default.basename(filePath, '.xml');
// let result
// if (filePath.endsWith('.xml') === false) throw filePath + ' does not have .xml extension'
// result = path.basename(filePath, '.xml')
const result = path_1.default.parse(filePath).name;
const identifierRegex = /^[_a-zA-Z][_a-zA-Z0-9]*$/;

@@ -70,3 +70,3 @@ if (result.match(identifierRegex) === null)

this.description(description)
.option('-i --id <id>', 'module ID to download')
.option('-i --id <id>', 'module ID to upload')
.argument('[files...]', 'local module file(s) to upload to the server')

@@ -176,3 +176,3 @@ .action(async (files, options) => {

if (fs.existsSync(filePath) === true) {
logger.info('file ' + filePath + ' already exists and will not be overwritten ');
logger.info('file ' + filePath + ' already exists. Remove it before launching the command if you want to overwrite.');
}

@@ -179,0 +179,0 @@ else {

@@ -32,2 +32,4 @@ #!/usr/bin/env ts-node

const Cmd_1 = require("./Cmd");
const DBClient_1 = require("./DBClient");
const form_data_1 = __importDefault(require("form-data"));
const logger = loglevel_1.default.getLogger("TableCommand.ts");

@@ -40,2 +42,7 @@ logger.setLevel("debug");

this.addCommand(new TableExportCmd());
this.addCommand(new TableImportCmd());
this.addCommand(new TableList('list', 'list database tables'));
this.addCommand(new TableList('l', '(l)ist database tables'));
this.addCommand(new TableQuery('query', 'query select table content'));
this.addCommand(new TableQuery('q', 'query select table content'));
}

@@ -57,4 +64,46 @@ }

throw 'dbManager undefined';
await commandImportExport(this.dbManager, 'to', tables, options);
// await commandImportExport(this.dbManager, 'to', tables, options)
try {
if (options.file === undefined && options.dir === undefined)
throw '--file or --dir mandatory';
if (options.file !== undefined && options.dir !== undefined)
throw '--file and --dir are mutually exclusive';
if (tables.length === 0)
throw 'at least one table name is mandatory';
if (tables.length > 1 && options.dir === undefined)
throw 'for multiple tables, --dir is mandatory';
for (let indi = 0; indi < tables.length; indi++) {
const tableName = tables[indi];
const dbTable = await this.dbManager.dbTableExist(tableName);
if (dbTable === undefined) {
logger.info('table ' + tableName + ' not found');
continue;
}
const filename = buildFilename(dbTable.name, options);
await this.copyTo(dbTable, filename);
}
}
catch (err) {
logger.error(err);
}
}
async copyTo(dbTable, filename) {
if (this.dbRemote === undefined)
throw 'dbRemote undefined';
try {
const writeStream = fs.createWriteStream(filename);
const response = await this.dbRemote.apiServer.get('/admin/export/' + dbTable.name, { responseType: 'stream' });
const stream = response;
stream.on('data', (data) => {
logger.debug('**** DATA ****', data.length);
const textDecoder = new TextDecoder();
const chunk = (textDecoder.decode(data));
writeStream.write(chunk);
});
stream.on('end', () => logger.debug('**** DONE ****'));
}
catch (err) {
logger.error(err);
}
}
}

@@ -65,2 +114,3 @@ class TableImportCmd extends Cmd_1.Cmd {

this.description('import from CSV file(s)')
.argument('<tables...>', 'table(s) to import')
.option('-f --file <file>', 'name of the file to import, defaults to <table_name>.csv')

@@ -74,5 +124,68 @@ .option('-d --dir <directory>', 'name of the directory where to find files to import')

throw 'dbManager undefined';
await commandImportExport(this.dbManager, 'from', tables, options);
// await commandImportExport(this.dbManager, 'to', tables, options)
try {
if (options.file === undefined && options.dir === undefined)
throw '--file or --dir mandatory';
if (options.file !== undefined && options.dir !== undefined)
throw '--file and --dir are mutually exclusive';
if (tables.length === 0)
throw 'at least one table name is mandatory';
if (tables.length > 1 && options.dir === undefined)
throw 'for multiple tables, --dir is mandatory';
for (let indi = 0; indi < tables.length; indi++) {
const tableName = tables[indi];
const dbTable = await this.dbManager.dbTableExist(tableName);
if (dbTable === undefined) {
logger.info('table ' + tableName + ' not found');
continue;
}
const filename = buildFilename(dbTable.name, options);
this.copyFrom(dbTable, filename);
}
}
catch (err) {
logger.error(err);
}
}
async copyFrom(dbTable, filename) {
if (this.dbRemote === undefined)
throw 'dbRemote undefined';
try {
const file = fs.createReadStream(filename);
const form = new form_data_1.default();
form.append('uploadFile', file);
const route = '/admin/import/' + dbTable.name;
const resp = await this.dbRemote.apiServer.post(route, form);
if (resp.status === 200) {
logger.debug(filename + ' uploaded');
}
}
catch (err) {
logger.error(err);
}
}
}
function buildFilename(tableName, options) {
let filename;
if (options.file !== undefined) {
if (fs.existsSync(options.file) && fs.lstatSync(options.file).isDirectory())
throw '--file ' + options.file + ' is a directory';
filename = options.file;
}
else if (options.dir === undefined)
throw '--file and --dir unspecified';
else if (fs.existsSync(options.dir) === false)
throw 'directory ' + options.dir + ' does not exist';
else if (fs.lstatSync(options.dir).isFile()) {
throw ("--dir " + options.dir + " is a file ");
}
else {
let directory = options.dir.trim();
if (directory[directory.length - 1] !== '/') {
directory += '/';
}
filename = directory + tableName + '.csv';
}
return filename;
}
const commandImportExport = async (dbManager, direction, tables, options) => {

@@ -96,51 +209,128 @@ logger.debug('tables : ', tables, 'options : ', options);

}
let lcols;
for (let indj = 0; indj < dbTable.columns.length; indj++) {
const dbColumn = dbTable.columns[indj];
if (lcols === undefined) {
lcols = "(";
psqlCmd(dbTable, direction, options);
}
}
catch (err) {
logger.error(err);
}
};
//--------------------------------------------------------------------------------------------------------------------
// function psqlCmd
// invoke local install of psql CLI
//--------------------------------------------------------------------------------------------------------------------
function psqlCmd(dbTable, direction, options) {
let lcols;
for (let indj = 0; indj < dbTable.columns.length; indj++) {
const dbColumn = dbTable.columns[indj];
if (lcols === undefined) {
lcols = "(";
}
else {
lcols += ",";
}
lcols += dbColumn.name;
}
lcols += ")";
let psql_cmd = "psql -c";
if (process.env.HEROKU_CLI !== undefined) {
psql_cmd = process.env.HEROKU_CLI + ' -c ';
}
let filename;
if (options.file !== undefined) {
if (fs.existsSync(options.file) && fs.lstatSync(options.file).isDirectory())
throw '--file ' + options.file + ' is a directory';
filename = options.file;
}
else if (options.dir === undefined)
throw '--file and --dir unspecified';
else if (fs.existsSync(options.dir) === false)
throw 'directory ' + options.dir + ' does not exist';
else if (fs.lstatSync(options.dir).isFile()) {
logger.debug("--dir " + options.dir + " is a file ");
}
else {
let directory = options.dir.trim();
if (directory[directory.length - 1] !== '/') {
directory += '/';
}
filename = directory + dbTable.name + '.csv';
}
let copy_cmd = "\\copy " + dbTable.name + lcols + direction + " '" + filename + "' csv header";
const shell_cmd = psql_cmd + '"' + copy_cmd + '"';
logger.debug(shell_cmd);
const child = (0, child_process_1.spawn)(shell_cmd.trim(), { stdio: 'inherit', shell: true });
}
//--------------------------------------------------------------------------------------------------------------------
// class TableList
//--------------------------------------------------------------------------------------------------------------------
class TableList extends Cmd_1.Cmd {
constructor(name, description) {
super(name);
this.description(description)
.option('-s --sort <columns>', 'sort list by column numbers (begins with 0) separated by comma')
.action(async (options) => {
await this.commandList(options);
});
}
async commandList(options) {
await this.prologue(options);
if (this.dbManager === undefined)
throw 'dbManager undefined';
const dbClient = new DBClient_1.DBClient(this.dbManager);
dbClient.selectFromTable('List of Tables', 'cyk_table', { fields: 'table_id,table_name,table_description,table_access', sort: options.sort || '1' });
}
}
//--------------------------------------------------------------------------------------------------------------------
// class TableQuery
//--------------------------------------------------------------------------------------------------------------------
class TableQuery extends Cmd_1.Cmd {
constructor(name, description) {
super(name);
this.description(description)
.argument('<table>', 'table to query')
.option('--where <clause_where_sql>', 'criteria in SQL syntax')
.option('-s --sort <columns>', 'sort by columns positions (begins by 0) separated by comma')
.option('-w --width <colwidth>', 'columns widths separated by comma')
.action(async (table, options) => {
this.commandQuery(table, options);
});
}
async commandQuery(table, options) {
try {
await this.prologue(options);
if (this.dbManager === undefined)
throw 'dbManager undefined';
const dbTable = await this.dbManager.dbTableExist(table);
if (dbTable === undefined)
throw 'table ' + table + ' not found';
let fields = '';
for (let ind = 0; ind < dbTable.columns.length; ind++) {
const dbColumn = dbTable.columns[ind];
let ok = false;
let fieldName = dbColumn.name;
if (dbColumn.dbType === 'text' || dbColumn.dbType === 'bytea') {
ok = false;
fieldName = 'length(' + dbColumn.name + ')';
}
else {
lcols += ",";
ok = true;
}
lcols += dbColumn.name;
if (ok === true) {
if (fields !== '')
fields += ',';
fields += fieldName;
}
}
lcols += ")";
let psql_cmd = "psql -c";
if (process.env.HEROKU_CLI !== undefined) {
psql_cmd = process.env.HEROKU_CLI + ' -c ';
logger.debug('commandQuery', table);
const dbClient = new DBClient_1.DBClient(this.dbManager);
let title = 'Table ' + table;
if (options.where !== undefined) {
title += ' where ' + options.where;
}
let filename;
if (options.file !== undefined) {
if (fs.existsSync(options.file) && fs.lstatSync(options.file).isDirectory())
throw '--file ' + options.file + ' is a directory';
filename = options.file;
}
else if (options.dir === undefined)
throw '--file and --dir unspecified';
else if (fs.existsSync(options.dir) === false)
throw 'directory ' + options.dir + ' does not exist';
else if (fs.lstatSync(options.dir).isFile()) {
logger.debug("--dir " + options.dir + " is a file ");
}
else {
let directory = options.dir.trim();
if (directory[directory.length - 1] !== '/') {
directory += '/';
}
filename = directory + tableName + '.csv';
}
let copy_cmd = "\\copy " + tableName + lcols + direction + " '" + filename + "' csv header";
const shell_cmd = psql_cmd + '"' + copy_cmd + '"';
logger.debug(shell_cmd);
const child = (0, child_process_1.spawn)(shell_cmd.trim(), { stdio: 'inherit', shell: true });
// exec(shell_cmd.trim(), (error, stdout, stderr) => {
// if (error) throw error
// logger.debug(stdout, stderr)
// })
dbClient.selectFromTable(title, table, { fields: fields, width: options.width, sort: options.sort || '1', where: options.where });
}
catch (err) {
logger.error(err);
}
}
catch (err) {
logger.error(err);
}
};
}
{
"name": "@cyklang/cli",
"version": "0.1.2",
"version": "0.2.0",
"description": "cyklang CLI",

@@ -14,3 +14,3 @@ "main": "build/index.js",

"dev": "nodemon -e ts --ignore build --exec \"npm run global\" ",
"test": "sudo npm i -g && cyk"
"test": "cyk test test/t*.xml"
},

@@ -24,3 +24,5 @@ "keywords": [],

"dotenv": "^16.0.1",
"form-data": "^4.0.0",
"loglevel": "^1.8.0",
"mime-types": "^2.1.35",
"pako": "^2.0.4",

@@ -30,2 +32,3 @@ "xml": "^1.0.1"

"devDependencies": {
"@types/mime-types": "^2.1.1",
"@types/pako": "^2.0.0",

@@ -32,0 +35,0 @@ "@types/sax": "^1.2.4",

@@ -11,2 +11,3 @@ import { DBManager, DBRemote, Structure } from "@cyklang/core";

dbManager: DBManager | undefined
dbRemote: DBRemote | undefined

@@ -27,9 +28,9 @@ constructor(name: string) {

const nodeCrypto = new NodeCrypto()
const dbRemote = new DBRemote(structure.scope, process.env.DBREMOTE_URL, nodeCrypto)
const login = await dbRemote.signin(process.env.USER_NAME, undefined, process.env.USER_PASSWORD)
this.dbRemote = new DBRemote(structure.scope, process.env.DBREMOTE_URL, nodeCrypto)
const login = await this.dbRemote.signin(process.env.USER_NAME, undefined, process.env.USER_PASSWORD)
// logger.debug(login)
this.dbManager = new DBManager(structure.scope, dbRemote)
this.dbManager = new DBManager(structure.scope, this.dbRemote)
await this.dbManager.initialize()
}
}

@@ -14,3 +14,3 @@ import { BasicType, DBColumn, DBExecuteRequest, DBManager, DBTable, ObjectData, parseXML, PrimitiveData } from "@cyklang/core";

async selectFromTable(title: string, tableName: string, options:
{ fields: string, sort?: string | undefined, where?: string | undefined }) {
{ fields: string, sort?: string | undefined, where?: string | undefined, width?: string | undefined }) {

@@ -30,3 +30,3 @@ try {

let order_by = ''
for (let ind = 0; ind < sortcols.length; ind++ ) {
for (let ind = 0; ind < sortcols.length; ind++) {
const coli = sortcols[ind]

@@ -37,3 +37,3 @@ const colname = colnames[Number(coli)]

}
logger.debug('order_by '+order_by)
logger.debug('order_by ' + order_by)
request.parameters.addVariable('order_by', stringDataType).data = new PrimitiveData(stringDataType, order_by)

@@ -48,7 +48,7 @@ }

// }
const xmlResult = await this.dbManager.dbExecute(request)
if (xmlResult === undefined) throw 'xmlResult undefined'
const tagXmlResult = parseXML('xmlResult', xmlResult)
const objXmlResult = (await objectDataType.parseData(tagXmlResult, this.dbManager.scope)) as ObjectData

@@ -59,9 +59,10 @@ const objectMeta = (objXmlResult.variables.getData('meta')) as ObjectData

if (xmlMeta === undefined) throw 'meta does not have ' + tableName + ' description'
const tagDBTable = parseXML('dbTable', xmlMeta)
const dbTable = new DBTable(tagDBTable)
const fields = options.fields.split(',')
const list = new List()
if (options.width !== undefined) list.width = options.width
for (let ind = 0; ind < fields.length; ind++) {

@@ -73,3 +74,3 @@ const field = fields[ind]

}
const objDataset = objXmlResult.variables.getData(tableName) as ObjectData

@@ -81,3 +82,3 @@ for (let ind = 0; ind < objDataset.variables.length(); ind++) {

logger.info(list.renderList(title))
}

@@ -91,2 +92,3 @@ catch (err) {

class List {
width = "0"
columns: Column[] = []

@@ -118,16 +120,40 @@ rows: Row[] = []

renderList(title: string): string {
// calculate column.width
// parse width option
const colws: number[] = []
const colws_ = this.width.split(',')
for (let ind = 0; ind < colws_.length; ind++) {
const colw = Number.parseInt(colws_[ind])
if (isNaN(colw)) {
const msg = '--width incorrect format : ' + this.width
throw msg
}
colws.push(colw)
}
logger.debug('colws', colws.join(','))
// calculate column.actualWidth
let total_width = 0
for (let indi = 0; indi < this.columns.length; indi++) {
const column = this.columns[indi]
column.width = column.label.length
if (indi < colws.length) column.width = colws[indi]
else column.width = colws[colws.length - 1]
column.actualWidth = column.label.length
this.rows.forEach((row) => {
const cell = row.cells[indi]
const renderedCell = this.renderCell(cell)
if (renderedCell.length > column.width) {
column.width = renderedCell.length
if (renderedCell.length > column.actualWidth) {
if (column.width === 0 || renderedCell.length < column.width)
column.actualWidth = renderedCell.length
else
column.actualWidth = column.width
}
})
if (total_width > 0) total_width += 3
total_width += column.width
total_width += column.actualWidth
}

@@ -143,6 +169,9 @@

// rows
for (let indj = 0; indj < this.rows.length; indj++ ) {
for (let indj = 0; indj < this.rows.length; indj++) {
const row = this.rows[indj]
this.lines.push(this.renderRow(row))
}
this.lines.push(this.renderSeparator())
this.lines.push('Number of lines : ' + this.rows.length)
return this.lines.join('\n')

@@ -153,6 +182,6 @@ }

let result = ''
for (let indi = 0; indi < this.columns.length; indi++ ) {
for (let indi = 0; indi < this.columns.length; indi++) {
const column = this.columns[indi]
if (result !== '') result += ' | '
result += this.renderCell(column.label, column.width, 'center')
result += this.renderCell(column.label, column.actualWidth, 'center')
}

@@ -164,3 +193,3 @@ return result

let result = ''
for (let indi = 0; indi < this.columns.length; indi++ ) {
for (let indi = 0; indi < this.columns.length; indi++) {
const column = this.columns[indi]

@@ -172,3 +201,3 @@ let justify: 'left' | 'right' | 'center' | undefined = 'left'

if (result !== '') result += ' | '
result += this.renderCell(row.cells[indi], column.width, justify)
result += this.renderCell(row.cells[indi], column.actualWidth, justify)
}

@@ -180,6 +209,6 @@ return result

let result = ''
for ( let indi = 0; indi < this.columns.length; indi++ ) {
for (let indi = 0; indi < this.columns.length; indi++) {
const column = this.columns[indi]
if (result !== '') result += '-+-'
result += '-'.repeat(column.width)
result += '-'.repeat(column.actualWidth)
}

@@ -197,16 +226,25 @@ return result

}
else if (value instanceof Date) {
const d = value as Date
result = d.toISOString()
}
else {
result = value.toString()
}
if (width !== undefined && result.length < width) {
if (justify === undefined || justify === 'left') {
result += ' '.repeat(width - result.length)
if (width !== undefined && width !== 0) {
if (result.length >= width) {
result = result.substring(0, width)
}
else if (justify === 'right') {
result = ' '.repeat(width - result.length) + result
}
else {
// justify === center
const before = Math.floor((width - result.length) / 2)
result = ' '.repeat(before) + result + ' '.repeat(width - result.length - before)
if (justify === undefined || justify === 'left') {
result += ' '.repeat(width - result.length)
}
else if (justify === 'right') {
result = ' '.repeat(width - result.length) + result
}
else {
// justify === center
const before = Math.floor((width - result.length) / 2)
result = ' '.repeat(before) + result + ' '.repeat(width - result.length - before)
}
}

@@ -225,2 +263,3 @@ }

width: number = 0
actualWidth: number = 0
constructor(name: string) {

@@ -227,0 +266,0 @@ this.name = name

@@ -11,2 +11,3 @@ #!/usr/bin/env node

import { InitCommand } from './InitCommand'
import { AssetCommand } from './AssetCommand'
const logger = loglevel.getLogger("index.ts")

@@ -20,2 +21,4 @@ logger.setLevel("debug")

program.addCommand(new InitCommand('init'))
program.addCommand(new AssetCommand('asset', 'manage assets'))
program.addCommand(new AssetCommand('a', 'manage assets'))
program.addCommand(new ModuleCommand('module'))

@@ -22,0 +25,0 @@ program.addCommand(new ModuleCommand('m'))

@@ -34,5 +34,7 @@ #!/usr/bin/env ts-node

function getModuleDBName(filePath: string): string {
let result
if (filePath.endsWith('.xml') === false) throw filePath + ' does not have .xml extension'
result = path.basename(filePath, '.xml')
// let result
// if (filePath.endsWith('.xml') === false) throw filePath + ' does not have .xml extension'
// result = path.basename(filePath, '.xml')
const result = path.parse(filePath).name
const identifierRegex = /^[_a-zA-Z][_a-zA-Z0-9]*$/

@@ -50,3 +52,3 @@ if (result.match(identifierRegex) === null) throw 'filename ' + result + ' does not match identifier syntax'

this.description(description)
.option('-i --id <id>', 'module ID to download')
.option('-i --id <id>', 'module ID to upload')
.argument('[files...]', 'local module file(s) to upload to the server')

@@ -161,3 +163,3 @@ .action(async (files: any, options: any) => {

if (fs.existsSync(filePath) === true) {
logger.info('file ' + filePath + ' already exists and will not be overwritten ')
logger.info('file ' + filePath + ' already exists. Remove it before launching the command if you want to overwrite.')
}

@@ -164,0 +166,0 @@ else {

#!/usr/bin/env ts-node
import { DBManager } from "@cyklang/core"
import { DBManager, DBTable } from "@cyklang/core"
import * as fs from "fs"

@@ -8,2 +8,6 @@ import loglevel from 'loglevel'

import { Cmd } from "./Cmd"
import { DBClient } from "./DBClient"
import { Stream } from "form-data"
import FormData from 'form-data'
const logger = loglevel.getLogger("TableCommand.ts")

@@ -17,2 +21,7 @@ logger.setLevel("debug")

this.addCommand(new TableExportCmd())
this.addCommand(new TableImportCmd())
this.addCommand(new TableList('list', 'list database tables'))
this.addCommand(new TableList('l', '(l)ist database tables'))
this.addCommand(new TableQuery('query', 'query select table content'))
this.addCommand(new TableQuery('q', 'query select table content'))
}

@@ -22,32 +31,145 @@ }

class TableExportCmd extends Cmd {
constructor() {
super('export')
this.description('export to CSV file(s)')
.argument('<tables...>', 'table(s) to export')
.option('-f --file <file>', 'name of the file to create, defaults to <table_name>.csv')
.option('-d --dir <directory>', 'name of the directory where to create exported files')
.action(async (tables, options) => this.commandExport( tables, options))
.argument('<tables...>', 'table(s) to export')
.option('-f --file <file>', 'name of the file to create, defaults to <table_name>.csv')
.option('-d --dir <directory>', 'name of the directory where to create exported files')
.action(async (tables, options) => this.commandExport(tables, options))
}
async commandExport(tables: string[], options: Options) {
await this.prologue(options)
if (this.dbManager === undefined) throw 'dbManager undefined'
await commandImportExport(this.dbManager, 'to', tables, options)
// await commandImportExport(this.dbManager, 'to', tables, options)
try {
if (options.file === undefined && options.dir === undefined) throw '--file or --dir mandatory'
if (options.file !== undefined && options.dir !== undefined) throw '--file and --dir are mutually exclusive'
if (tables.length === 0) throw 'at least one table name is mandatory'
if (tables.length > 1 && options.dir === undefined) throw 'for multiple tables, --dir is mandatory'
for (let indi = 0; indi < tables.length; indi++) {
const tableName = tables[indi]
const dbTable = await this.dbManager.dbTableExist(tableName)
if (dbTable === undefined) {
logger.info('table ' + tableName + ' not found')
continue
}
const filename = buildFilename(dbTable.name, options)
await this.copyTo(dbTable, filename)
}
}
catch (err) {
logger.error(err)
}
}
async copyTo(dbTable: DBTable, filename: string) {
if (this.dbRemote === undefined) throw 'dbRemote undefined'
try {
const writeStream = fs.createWriteStream(filename)
const response = await this.dbRemote.apiServer.get('/admin/export/' + dbTable.name, { responseType: 'stream' })
const stream = response as Stream
stream.on('data', (data: Uint8Array) => {
logger.debug('**** DATA ****', data.length)
const textDecoder = new TextDecoder()
const chunk = (textDecoder.decode(data))
writeStream.write(chunk)
})
stream.on('end', () => logger.debug('**** DONE ****'))
}
catch (err) {
logger.error(err)
}
}
}
class TableImportCmd extends Cmd {
constructor() {
super('import')
this.description('import from CSV file(s)')
.option('-f --file <file>', 'name of the file to import, defaults to <table_name>.csv')
.option('-d --dir <directory>', 'name of the directory where to find files to import')
.action(async (tables, options) => this.commandImport(tables, options))
.argument('<tables...>', 'table(s) to import')
.option('-f --file <file>', 'name of the file to import, defaults to <table_name>.csv')
.option('-d --dir <directory>', 'name of the directory where to find files to import')
.action(async (tables, options) => this.commandImport(tables, options))
}
async commandImport(tables: string[], options: Options) {
await this.prologue(options)
if (this.dbManager === undefined) throw 'dbManager undefined'
await commandImportExport(this.dbManager, 'from', tables, options)
// await commandImportExport(this.dbManager, 'to', tables, options)
try {
if (options.file === undefined && options.dir === undefined) throw '--file or --dir mandatory'
if (options.file !== undefined && options.dir !== undefined) throw '--file and --dir are mutually exclusive'
if (tables.length === 0) throw 'at least one table name is mandatory'
if (tables.length > 1 && options.dir === undefined) throw 'for multiple tables, --dir is mandatory'
for (let indi = 0; indi < tables.length; indi++) {
const tableName = tables[indi]
const dbTable = await this.dbManager.dbTableExist(tableName)
if (dbTable === undefined) {
logger.info('table ' + tableName + ' not found')
continue
}
const filename = buildFilename(dbTable.name, options)
this.copyFrom(dbTable, filename)
}
}
catch (err) {
logger.error(err)
}
}
async copyFrom(dbTable: DBTable, filename: string) {
if (this.dbRemote === undefined) throw 'dbRemote undefined'
try {
const file = fs.createReadStream(filename)
const form = new FormData()
form.append('uploadFile', file)
const route = '/admin/import/' + dbTable.name
const resp = await this.dbRemote.apiServer.post(route, form)
if (resp.status === 200) {
logger.debug(filename + ' uploaded')
}
}
catch (err) {
logger.error(err)
}
}
}
function buildFilename(tableName: string, options: Options): string {
let filename
if (options.file !== undefined) {
if (fs.existsSync(options.file) && fs.lstatSync(options.file).isDirectory())
throw '--file ' + options.file + ' is a directory'
filename = options.file
}
else if (options.dir === undefined)
throw '--file and --dir unspecified'
else if (fs.existsSync(options.dir) === false)
throw 'directory ' + options.dir + ' does not exist'
else if (fs.lstatSync(options.dir).isFile()) {
throw ("--dir " + options.dir + " is a file ")
}
else {
let directory = options.dir.trim()
if (directory[directory.length - 1] !== '/') {
directory += '/'
}
filename = directory + tableName + '.csv'
}
return filename
}
interface Options {

@@ -75,57 +197,148 @@ env: string | undefined

}
let lcols: string | undefined
for (let indj = 0; indj < dbTable.columns.length; indj++) {
const dbColumn = dbTable.columns[indj]
if (lcols === undefined) {
lcols = "("
}
else {
lcols += ","
}
lcols += dbColumn.name
}
lcols += ")"
psqlCmd(dbTable, direction, options)
}
}
catch (err) {
logger.error(err)
}
}
let psql_cmd = "psql -c"
if (process.env.HEROKU_CLI !== undefined) {
psql_cmd = process.env.HEROKU_CLI + ' -c '
}
let filename
if (options.file !== undefined) {
if (fs.existsSync(options.file) && fs.lstatSync(options.file).isDirectory())
throw '--file ' + options.file + ' is a directory'
filename = options.file
}
else if (options.dir === undefined)
throw '--file and --dir unspecified'
else if (fs.existsSync(options.dir) === false)
throw 'directory ' + options.dir + ' does not exist'
else if (fs.lstatSync(options.dir).isFile()) {
logger.debug("--dir " + options.dir + " is a file ")
}
else {
let directory = options.dir.trim()
if (directory[directory.length - 1] !== '/') {
directory += '/'
}
filename = directory + tableName + '.csv'
}
//--------------------------------------------------------------------------------------------------------------------
// function psqlCmd
// invoke local install of psql CLI
//--------------------------------------------------------------------------------------------------------------------
let copy_cmd = "\\copy " + tableName + lcols + direction + " '" + filename + "' csv header"
const shell_cmd = psql_cmd + '"' + copy_cmd + '"'
logger.debug(shell_cmd)
const child = spawn(shell_cmd.trim(), { stdio: 'inherit', shell: true })
// exec(shell_cmd.trim(), (error, stdout, stderr) => {
// if (error) throw error
// logger.debug(stdout, stderr)
// })
function psqlCmd(dbTable: DBTable, direction: 'from' | 'to', options: Options,) {
let lcols: string | undefined
for (let indj = 0; indj < dbTable.columns.length; indj++) {
const dbColumn = dbTable.columns[indj]
if (lcols === undefined) {
lcols = "("
}
else {
lcols += ","
}
lcols += dbColumn.name
}
catch (err) {
logger.error(err)
lcols += ")"
let psql_cmd = "psql -c"
if (process.env.HEROKU_CLI !== undefined) {
psql_cmd = process.env.HEROKU_CLI + ' -c '
}
let filename
if (options.file !== undefined) {
if (fs.existsSync(options.file) && fs.lstatSync(options.file).isDirectory())
throw '--file ' + options.file + ' is a directory'
filename = options.file
}
else if (options.dir === undefined)
throw '--file and --dir unspecified'
else if (fs.existsSync(options.dir) === false)
throw 'directory ' + options.dir + ' does not exist'
else if (fs.lstatSync(options.dir).isFile()) {
logger.debug("--dir " + options.dir + " is a file ")
}
else {
let directory = options.dir.trim()
if (directory[directory.length - 1] !== '/') {
directory += '/'
}
filename = directory + dbTable.name + '.csv'
}
let copy_cmd = "\\copy " + dbTable.name + lcols + direction + " '" + filename + "' csv header"
const shell_cmd = psql_cmd + '"' + copy_cmd + '"'
logger.debug(shell_cmd)
const child = spawn(shell_cmd.trim(), { stdio: 'inherit', shell: true })
}
//--------------------------------------------------------------------------------------------------------------------
// class TableList
//--------------------------------------------------------------------------------------------------------------------
class TableList extends Cmd {
constructor(name: string, description: string) {
super(name)
this.description(description)
.option('-s --sort <columns>', 'sort list by column numbers (begins with 0) separated by comma')
.action(async (options: any) => {
await this.commandList(options)
})
}
async commandList(options: any) {
await this.prologue(options)
if (this.dbManager === undefined) throw 'dbManager undefined'
const dbClient = new DBClient(this.dbManager)
dbClient.selectFromTable('List of Tables', 'cyk_table',
{ fields: 'table_id,table_name,table_description,table_access', sort: options.sort || '1' }
)
}
}
//--------------------------------------------------------------------------------------------------------------------
// class TableQuery
//--------------------------------------------------------------------------------------------------------------------
class TableQuery extends Cmd {
constructor(name: string, description: string) {
super(name)
this.description(description)
.argument('<table>', 'table to query')
.option('--where <clause_where_sql>', 'criteria in SQL syntax')
.option('-s --sort <columns>', 'sort by columns positions (begins by 0) separated by comma')
.option('-w --width <colwidth>', 'columns widths separated by comma')
.action(async (table, options) => {
this.commandQuery(table, options)
})
}
async commandQuery(table: string, options: any) {
try {
await this.prologue(options)
if (this.dbManager === undefined) throw 'dbManager undefined'
const dbTable = await this.dbManager.dbTableExist(table)
if (dbTable === undefined) throw 'table ' + table + ' not found'
let fields = ''
for (let ind = 0; ind < dbTable.columns.length; ind++) {
const dbColumn = dbTable.columns[ind]
let ok = false
let fieldName = dbColumn.name
if (dbColumn.dbType === 'text' || dbColumn.dbType === 'bytea') {
ok = false
fieldName = 'length(' + dbColumn.name + ')'
}
else {
ok = true
}
if (ok === true) {
if (fields !== '') fields += ','
fields += fieldName
}
}
logger.debug('commandQuery', table)
const dbClient = new DBClient(this.dbManager)
let title = 'Table ' + table
if (options.where !== undefined) {
title += ' where ' + options.where
}
dbClient.selectFromTable(title, table,
{ fields: fields, width: options.width, sort: options.sort || '1', where: options.where })
}
catch (err) {
logger.error(err)
}
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc