@cyklang/cli
Advanced tools
Comparing version 0.5.4 to 0.5.5
import { Command } from "commander"; | ||
import { DBManager, DBRemote } from "@cyklang/core"; | ||
export declare class AssetCommand extends Command { | ||
constructor(name: string, description: string); | ||
} | ||
export interface FileDescriptor { | ||
path: string; | ||
mtime: Date; | ||
id?: number; | ||
} | ||
/** | ||
* function uploadDirectory | ||
* @param source | ||
* @param dest | ||
* @param options {yes: no confirmation, auth: basic/token/cookie/undefined} | ||
* @param dbManager | ||
* @param dbRemote | ||
*/ | ||
export declare function uploadDirectory(source: string, dest: string, options: any, dbManager: DBManager | undefined, dbRemote: DBRemote | undefined): Promise<void>; | ||
/** | ||
* function uploadAsset | ||
* @param upload | ||
* @param route | ||
* @param dbManager | ||
* @param dbRemote | ||
* @param auth | ||
*/ | ||
export declare function uploadAsset(upload: FileDescriptor, route: string, dbManager: DBManager | undefined, dbRemote: DBRemote | undefined, auth?: string): Promise<void>; |
@@ -29,3 +29,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AssetCommand = void 0; | ||
exports.uploadAsset = exports.uploadDirectory = exports.AssetCommand = void 0; | ||
const commander_1 = require("commander"); | ||
@@ -188,6 +188,2 @@ const loglevel_1 = require("loglevel"); | ||
super(name); | ||
//---------------------------------------------------------------------------------------------- | ||
// file2exclude | ||
//---------------------------------------------------------------------------------------------- | ||
this.ignorePatterns = ['.git', 'node_modules']; | ||
this.description(description) | ||
@@ -205,12 +201,2 @@ .option('-i --id <id>', 'asset id or pathname whose properties are updated') | ||
} | ||
mimetypeLookup(filename) { | ||
let result; | ||
if (path_1.default.extname(filename) === '.cyk') { | ||
result = 'application/xml'; | ||
} | ||
else { | ||
result = mime_types_1.default.lookup(filename); | ||
} | ||
return result; | ||
} | ||
/** | ||
@@ -280,3 +266,3 @@ * method commandU | ||
if (options.clean) { | ||
await this.cleanDestination(dest); | ||
await cleanDestination(dest, this.dbManager, this.dbRemote); | ||
} | ||
@@ -289,3 +275,3 @@ for (let ind = 0; ind < sources.length; ind++) { | ||
if (filestat.isDirectory() === true) { | ||
await this.uploadDirectory(source, dest, options); | ||
await uploadDirectory(source, dest, options, this.dbManager, this.dbRemote); | ||
} | ||
@@ -295,3 +281,3 @@ else if (filestat.isFile() === true) { | ||
logger.debug('upload file ' + source + ' to ' + dest + base); | ||
await this.uploadAsset({ path: source, mtime: filestat.mtime }, dest + base, options.auth); | ||
await uploadAsset({ path: source, mtime: filestat.mtime }, dest + base, this.dbManager, this.dbRemote, options.auth); | ||
} | ||
@@ -304,178 +290,221 @@ } | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// cleanDestination | ||
//---------------------------------------------------------------------------------------------- | ||
async cleanDestination(dest) { | ||
const remoteList = await scanAssets(this.dbManager); | ||
for (let ind = 0; ind < remoteList.length; ind++) { | ||
const fd = remoteList[ind]; | ||
if (fd.path.startsWith(dest)) { | ||
const url = '/api/admin/assets/' + fd.id; | ||
await this.dbRemote?.apiServer.delete(url); | ||
} | ||
} | ||
/** | ||
* function cleanDestination | ||
* @param dest | ||
* @param dbManager | ||
* @param dbRemote | ||
*/ | ||
async function cleanDestination(dest, dbManager, dbRemote) { | ||
const remoteList = await scanAssets(dbManager); | ||
for (let ind = 0; ind < remoteList.length; ind++) { | ||
const fd = remoteList[ind]; | ||
if (fd.path.startsWith(dest)) { | ||
const url = '/api/admin/assets/' + fd.id; | ||
await dbRemote?.apiServer.delete(url); | ||
} | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// uploadDirectory | ||
//---------------------------------------------------------------------------------------------- | ||
async uploadDirectory(source, dest, options) { | ||
const localList = []; | ||
let dirName; | ||
if (source.substring(source.length - 1) === '/') { | ||
// trailing directory separator | ||
dirName = source; | ||
} | ||
/** | ||
* function uploadDirectory | ||
* @param source | ||
* @param dest | ||
* @param options {yes: no confirmation, auth: basic/token/cookie/undefined} | ||
* @param dbManager | ||
* @param dbRemote | ||
*/ | ||
async function uploadDirectory(source, dest, options, dbManager, dbRemote) { | ||
const localList = []; | ||
let dirName; | ||
if (source.substring(source.length - 1) === '/') { | ||
// trailing directory separator | ||
dirName = source; | ||
} | ||
else { | ||
dirName = source + '/'; | ||
} | ||
// logger.debug('options', options) | ||
scanDir(dirName, localList); | ||
const remoteList = await scanAssets(dbManager); | ||
const uploadList = buildUploadList(dirName, dest, localList, remoteList); | ||
// logger.info(fileNames.join('\n')) | ||
if (uploadList.length === 0) | ||
throw 'None file to upload'; | ||
let uploadConfirmed = (options.yes !== undefined); | ||
if (uploadConfirmed === false) { | ||
const reply = await inquirer_1.default.prompt({ type: 'confirm', name: 'confirm', message: 'Do you want to upload this(these) ' + uploadList.length + ' file(s) ?' }); | ||
if (reply.confirm === true) | ||
uploadConfirmed = true; | ||
} | ||
if (uploadConfirmed === true) { | ||
await uploadFiles(dirName, uploadList, dest, dbManager, dbRemote, options.auth); | ||
} | ||
} | ||
exports.uploadDirectory = uploadDirectory; | ||
/** | ||
* function buildUploadList | ||
* @param dirName | ||
* @param dest | ||
* @param localList | ||
* @param remoteList | ||
* @returns | ||
*/ | ||
function buildUploadList(dirName, dest, localList, remoteList) { | ||
const result = []; | ||
const remoteMap = new Map(); | ||
for (let ind = 0; ind < remoteList.length; ind++) { | ||
const remote = remoteList[ind]; | ||
remoteMap.set(remote.path, remote); | ||
} | ||
for (let ind = 0; ind < localList.length; ind++) { | ||
const localDesc = localList[ind]; | ||
const route = dest + localDesc.path.substring(dirName.length); | ||
const remoteDesc = remoteMap.get(route); | ||
if (remoteDesc === undefined || remoteDesc.mtime.getTime() + 1000 < localDesc.mtime.getTime()) { | ||
if (remoteDesc === undefined) | ||
logger.debug('remoteDesc undefined'); | ||
else | ||
logger.debug('remoteDesc.mtime ' + remoteDesc.mtime.getTime(), 'localDesc.mtime ' + localDesc.mtime.getTime()); | ||
logger.info(localDesc.path); | ||
result.push(localDesc); | ||
} | ||
else { | ||
dirName = source + '/'; | ||
} | ||
// logger.debug('options', options) | ||
this.scanDir(dirName, localList); | ||
const remoteList = await scanAssets(this.dbManager); | ||
const uploadList = this.buildUploadList(dirName, dest, localList, remoteList); | ||
// logger.info(fileNames.join('\n')) | ||
if (uploadList.length === 0) | ||
throw 'None file to upload'; | ||
let uploadConfirmed = (options.yes !== undefined); | ||
if (uploadConfirmed === false) { | ||
const reply = await inquirer_1.default.prompt({ type: 'confirm', name: 'confirm', message: 'Do you want to upload this(these) ' + uploadList.length + ' file(s) ?' }); | ||
if (reply.confirm === true) | ||
uploadConfirmed = true; | ||
} | ||
if (uploadConfirmed === true) { | ||
await this.uploadFiles(dirName, uploadList, dest, options.auth); | ||
} | ||
// const rl = readline.createInterface(process.stdin, process.stdout) | ||
// rl.question('Do you want to upload this(these) ' + uploadList.length + ' file(s) (Y/N/y/n) ?', async (reply) => { | ||
// rl.close() | ||
// if (reply !== 'Y' && reply !== 'y') { | ||
// logger.info('upload cancelled') | ||
// return | ||
// } | ||
// await this.uploadFiles(dirName, uploadList, dest) | ||
// }) | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// buildUploadList | ||
//---------------------------------------------------------------------------------------------- | ||
buildUploadList(dirName, dest, localList, remoteList) { | ||
const result = []; | ||
const remoteMap = new Map(); | ||
for (let ind = 0; ind < remoteList.length; ind++) { | ||
const remote = remoteList[ind]; | ||
remoteMap.set(remote.path, remote); | ||
return result; | ||
} | ||
/** | ||
* function scanDir | ||
* @param dirName | ||
* @param result | ||
*/ | ||
function scanDir(dirName, result) { | ||
const files = fs.readdirSync(dirName); | ||
for (let ind = 0; ind < files.length; ind++) { | ||
const fileName = files[ind]; | ||
if (file2exclude(fileName) === true) | ||
continue; | ||
const fstat = fs.statSync(dirName + fileName); | ||
if (fstat.isDirectory() === true) { | ||
scanDir(dirName + fileName + '/', result); | ||
} | ||
for (let ind = 0; ind < localList.length; ind++) { | ||
const localDesc = localList[ind]; | ||
const route = dest + localDesc.path.substring(dirName.length); | ||
const remoteDesc = remoteMap.get(route); | ||
if (remoteDesc === undefined || remoteDesc.mtime.getTime() + 1000 < localDesc.mtime.getTime()) { | ||
if (remoteDesc === undefined) | ||
logger.debug('remoteDesc undefined'); | ||
else | ||
logger.debug('remoteDesc.mtime ' + remoteDesc.mtime.getTime(), 'localDesc.mtime ' + localDesc.mtime.getTime()); | ||
logger.info(localDesc.path); | ||
result.push(localDesc); | ||
} | ||
} | ||
return result; | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// scanDir | ||
//---------------------------------------------------------------------------------------------- | ||
scanDir(dirName, result) { | ||
const files = fs.readdirSync(dirName); | ||
for (let ind = 0; ind < files.length; ind++) { | ||
const fileName = files[ind]; | ||
if (this.file2exclude(fileName) === true) | ||
else { | ||
if (mimetypeLookup(fileName) === false) { | ||
logger.info(fileName + ' file extension is unknown and will not be uploaded'); | ||
continue; | ||
const fstat = fs.statSync(dirName + fileName); | ||
if (fstat.isDirectory() === true) { | ||
this.scanDir(dirName + fileName + '/', result); | ||
} | ||
else { | ||
if (this.mimetypeLookup(fileName) === false) { | ||
logger.info(fileName + ' file extension is unknown and will not be uploaded'); | ||
continue; | ||
} | ||
//const dbAssetExist = this.dbManager?.dbAssetExist() | ||
result.push({ path: dirName + fileName, mtime: fstat.mtime }); | ||
// logger.debug(dirName + '/' + fileName) | ||
} | ||
//const dbAssetExist = this.dbManager?.dbAssetExist() | ||
result.push({ path: dirName + fileName, mtime: fstat.mtime }); | ||
// logger.debug(dirName + '/' + fileName) | ||
} | ||
} | ||
file2exclude(fileName) { | ||
let result = false; | ||
this.ignorePatterns.forEach((pattern) => { | ||
if (fileName === pattern) | ||
result = true; | ||
}); | ||
return result; | ||
} | ||
const ignorePatterns = ['.git', 'node_modules']; | ||
/** | ||
* function file2exclude | ||
* @param fileName | ||
* @returns | ||
*/ | ||
function file2exclude(fileName) { | ||
let result = false; | ||
ignorePatterns.forEach((pattern) => { | ||
if (fileName === pattern) | ||
result = true; | ||
}); | ||
return result; | ||
} | ||
/** | ||
* function uploadFiles | ||
* @param dirName | ||
* @param uploadList | ||
* @param dest | ||
* @param dbManager | ||
* @param dbRemote | ||
* @param auth | ||
*/ | ||
async function uploadFiles(dirName, uploadList, dest, dbManager, dbRemote, auth) { | ||
for (let ind = 0; ind < uploadList.length; ind++) { | ||
const upload = uploadList[ind]; | ||
const route = dest + upload.path.substring(dirName.length); | ||
logger.debug('upload ' + upload.path + ' to ' + route); | ||
await uploadAsset(upload, route, dbManager, dbRemote, auth); | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// uploadFiles | ||
//---------------------------------------------------------------------------------------------- | ||
async uploadFiles(dirName, uploadList, dest, auth) { | ||
for (let ind = 0; ind < uploadList.length; ind++) { | ||
const upload = uploadList[ind]; | ||
const route = dest + upload.path.substring(dirName.length); | ||
logger.debug('upload ' + upload.path + ' to ' + route); | ||
await this.uploadAsset(upload, route, auth); | ||
} | ||
/** | ||
* function uploadAsset | ||
* @param upload | ||
* @param route | ||
* @param dbManager | ||
* @param dbRemote | ||
* @param auth | ||
*/ | ||
async function uploadAsset(upload, route, dbManager, dbRemote, auth) { | ||
// logger.debug('uploadAsset ' + upload.path + ' to route ' + route + ' with mimetype ' + this.mimetypeLookup(upload.path) + ', auth : ' + auth) | ||
try { | ||
let dbAsset = await dbManager?.dbAssetExist(route); | ||
if (dbAsset === undefined) { | ||
dbAsset = new core_1.DBAsset(); | ||
} | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// uploadAsset | ||
//---------------------------------------------------------------------------------------------- | ||
async uploadAsset(upload, route, auth) { | ||
// logger.debug('uploadAsset ' + upload.path + ' to route ' + route + ' with mimetype ' + this.mimetypeLookup(upload.path) + ', auth : ' + auth) | ||
try { | ||
let dbAsset = await this.dbManager?.dbAssetExist(route); | ||
if (dbAsset === undefined) { | ||
dbAsset = new core_1.DBAsset(); | ||
} | ||
const mimetype = this.mimetypeLookup(upload.path); | ||
if (mimetype === false) | ||
throw 'mimetype false for ' + upload; | ||
dbAsset.mimetype = mimetype; | ||
dbAsset.route = route; | ||
dbAsset.auth = auth; | ||
if (dbAsset.auth === 'none') | ||
dbAsset.auth = undefined; | ||
// const fstat = fs.statSync(fileName) | ||
dbAsset.last_update = upload.mtime; | ||
// const contentBuffer = fs.readFileSync(fileName) | ||
// dbAsset.content = contentBuffer | ||
// logger.debug('dbAsset.content length ' + dbAsset.content.length) | ||
if (dbAsset.id === undefined) { | ||
dbAsset.id = await this.dbManager?.dbAssetInsert(dbAsset); | ||
logger.info('inserted asset ' + dbAsset.id + ' route ' + dbAsset.route); | ||
} | ||
else { | ||
await this.dbManager?.dbAssetUpdate(dbAsset); | ||
logger.info('updated asset ' + dbAsset.route); | ||
} | ||
await this.uploadAssetContent(dbAsset, upload.path); | ||
const mimetype = mimetypeLookup(upload.path); | ||
if (mimetype === false) | ||
throw 'mimetype false for ' + upload; | ||
dbAsset.mimetype = mimetype; | ||
dbAsset.route = route; | ||
dbAsset.auth = auth; | ||
if (dbAsset.auth === 'none') | ||
dbAsset.auth = undefined; | ||
// const fstat = fs.statSync(fileName) | ||
dbAsset.last_update = upload.mtime; | ||
// const contentBuffer = fs.readFileSync(fileName) | ||
// dbAsset.content = contentBuffer | ||
// logger.debug('dbAsset.content length ' + dbAsset.content.length) | ||
if (dbAsset.id === undefined) { | ||
dbAsset.id = await dbManager?.dbAssetInsert(dbAsset); | ||
logger.info('inserted asset ' + dbAsset.id + ' route ' + dbAsset.route); | ||
} | ||
catch (err) { | ||
logger.error(err); | ||
else { | ||
await dbManager?.dbAssetUpdate(dbAsset); | ||
logger.info('updated asset ' + dbAsset.route); | ||
} | ||
await uploadAssetContent(dbAsset, upload.path, dbRemote); | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// uploadAssetContent | ||
//---------------------------------------------------------------------------------------------- | ||
async uploadAssetContent(dbAsset, fileName) { | ||
logger.debug('uploadAssetContent file ' + fileName + ' to path ' + path_1.default); | ||
try { | ||
const file = fs.createReadStream(fileName); | ||
const form = new form_data_1.default(); | ||
form.append('uploadFile', file); | ||
const route = '/api/upload/cyk_asset/asset_content?asset_id=' + dbAsset.id; | ||
const resp = await this.dbRemote?.apiServer.post(route, form); | ||
if (resp.status === 200) { | ||
logger.info(fileName + ' uploaded'); | ||
} | ||
catch (err) { | ||
logger.error(err); | ||
} | ||
} | ||
exports.uploadAsset = uploadAsset; | ||
/** | ||
* function mimetypeLookup | ||
* @param filename | ||
* @returns | ||
*/ | ||
function mimetypeLookup(filename) { | ||
let result; | ||
if (path_1.default.extname(filename) === '.cyk') { | ||
result = 'application/xml'; | ||
} | ||
else { | ||
result = mime_types_1.default.lookup(filename); | ||
} | ||
return result; | ||
} | ||
/** | ||
* function uploadAssetContent | ||
* @param dbAsset | ||
* @param fileName | ||
* @param dbRemote | ||
*/ | ||
async function uploadAssetContent(dbAsset, fileName, dbRemote) { | ||
logger.debug('uploadAssetContent file ' + fileName + ' to path ' + path_1.default); | ||
try { | ||
const file = fs.createReadStream(fileName); | ||
const form = new form_data_1.default(); | ||
form.append('uploadFile', file); | ||
const route = '/api/upload/cyk_asset/asset_content?asset_id=' + dbAsset.id; | ||
const resp = await dbRemote?.apiServer.post(route, form); | ||
if (resp.status === 200) { | ||
logger.info(fileName + ' uploaded'); | ||
} | ||
catch (err) { | ||
logger.error(err); | ||
} | ||
} | ||
catch (err) { | ||
logger.error(err); | ||
} | ||
} |
@@ -25,14 +25,19 @@ import { DBManager, DBRemote, SigninResponse } from "@cyklang/core"; | ||
}>; | ||
/** | ||
* method runShellCommand | ||
* @param command | ||
*/ | ||
runShellCommand(command: string, args: string[]): Promise<void>; | ||
/** | ||
* | ||
* @param command | ||
* @param args | ||
* @returns | ||
*/ | ||
spawnCommand(command: string, args: string[]): Promise<void>; | ||
} | ||
/** | ||
* method runShellCommand | ||
* @param command | ||
*/ | ||
export declare function runShellCommand(command: string, args: string[]): Promise<void>; | ||
/** | ||
* function spawnCommand | ||
* @param command | ||
* @param args | ||
* @returns | ||
*/ | ||
export declare function spawnCommand(command: string, args: string[]): Promise<void>; | ||
/** | ||
* function readPackageJson | ||
* @returns | ||
*/ | ||
export declare function readPackageJson(): Promise<any>; |
121
build/Cmd.js
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -6,3 +29,3 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Cmd = void 0; | ||
exports.readPackageJson = exports.spawnCommand = exports.runShellCommand = exports.Cmd = void 0; | ||
const core_1 = require("@cyklang/core"); | ||
@@ -16,2 +39,3 @@ const commander_1 = require("commander"); | ||
const kolorist_1 = require("kolorist"); | ||
const fs = __importStar(require("fs")); | ||
const logger = loglevel_1.default.getLogger('Cmd.ts'); | ||
@@ -105,43 +129,62 @@ logger.setLevel('debug'); | ||
} | ||
/** | ||
* method runShellCommand | ||
* @param command | ||
*/ | ||
async runShellCommand(command, args) { | ||
try { | ||
await this.spawnCommand(command, args); | ||
// console.log(command) | ||
// const result = await this.executeCommand(command); | ||
// console.log(result.stdout); | ||
// if (result.stderr && result.stderr.trim() !== '') | ||
// console.error(result.stderr); | ||
} | ||
catch (error) { | ||
console.error('Error running "' + command + '":', error); | ||
throw error; | ||
} | ||
} | ||
exports.Cmd = Cmd; | ||
/** | ||
* method runShellCommand | ||
* @param command | ||
*/ | ||
async function runShellCommand(command, args) { | ||
try { | ||
await spawnCommand(command, args); | ||
// console.log(command) | ||
// const result = await this.executeCommand(command); | ||
// console.log(result.stdout); | ||
// if (result.stderr && result.stderr.trim() !== '') | ||
// console.error(result.stderr); | ||
} | ||
/** | ||
* | ||
* @param command | ||
* @param args | ||
* @returns | ||
*/ | ||
spawnCommand(command, args) { | ||
console.log(); | ||
console.log([command, ...args, '...'].join(' ')); | ||
const child_process = (0, child_process_1.spawn)(command, args, { stdio: 'inherit' }); | ||
return new Promise((resolve, reject) => { | ||
child_process.on('close', (code) => { | ||
if (code === 0) { | ||
console.log((0, kolorist_1.green)('*') + ' ' + [command, ...args].join(' ')); | ||
resolve(); | ||
} | ||
else { | ||
reject(new Error([command, ...args].join(' ') + ' --> Error ' + code)); | ||
} | ||
}); | ||
catch (error) { | ||
console.error('Error running "' + command + '":', error); | ||
throw error; | ||
} | ||
} | ||
exports.runShellCommand = runShellCommand; | ||
/** | ||
* function spawnCommand | ||
* @param command | ||
* @param args | ||
* @returns | ||
*/ | ||
function spawnCommand(command, args) { | ||
console.log(); | ||
console.log([command, ...args, '...'].join(' ')); | ||
const child_process = (0, child_process_1.spawn)(command, args, { stdio: 'inherit' }); | ||
return new Promise((resolve, reject) => { | ||
child_process.on('close', (code) => { | ||
if (code === 0) { | ||
console.log((0, kolorist_1.green)('*') + ' ' + [command, ...args].join(' ')); | ||
resolve(); | ||
} | ||
else { | ||
reject(new Error([command, ...args].join(' ') + ' --> Error ' + code)); | ||
} | ||
}); | ||
}); | ||
} | ||
exports.spawnCommand = spawnCommand; | ||
/** | ||
* function readPackageJson | ||
* @returns | ||
*/ | ||
async function readPackageJson() { | ||
try { | ||
if (!fs.existsSync("package.json")) | ||
throw 'package.json not found'; | ||
const fileContent = fs.readFileSync("package.json"); | ||
return JSON.parse(fileContent.toString()); | ||
} | ||
catch (err) { | ||
console.error(err); | ||
throw err; | ||
} | ||
} | ||
exports.Cmd = Cmd; | ||
exports.readPackageJson = readPackageJson; |
@@ -126,2 +126,3 @@ "use strict"; | ||
await this.dbManager.dbModuleDelete(dbModule); | ||
logger.info('module ' + dbname + ' (id ' + dbModule.id + ' deleted)'); | ||
} | ||
@@ -128,0 +129,0 @@ catch (err) { |
@@ -18,2 +18,3 @@ #!/usr/bin/env node | ||
const OpenCommand_1 = require("./OpenCommand"); | ||
const UninstallCommand_1 = require("./UninstallCommand"); | ||
const logger = loglevel_1.default.getLogger("index.ts"); | ||
@@ -23,5 +24,6 @@ logger.setLevel("debug"); | ||
program.name('cyk').description('cyklang CLI') | ||
.version('0.5.4'); | ||
.version('0.5.5'); | ||
program.addCommand(new InstallCommand_1.InstallCommand('install')); | ||
program.addCommand(new InstallCommand_1.InstallCommand('i')); | ||
program.addCommand(new UninstallCommand_1.UninstallCommand('uninstall')); | ||
program.addCommand(new AssetCommand_1.AssetCommand('asset', 'manage assets')); | ||
@@ -28,0 +30,0 @@ program.addCommand(new AssetCommand_1.AssetCommand('a', 'manage assets')); |
import { Cmd } from "./Cmd"; | ||
import { DBManager, DBRemote } from "@cyklang/core"; | ||
export declare class InstallCommand extends Cmd { | ||
constructor(name: string); | ||
install(node_package: string, options: any): Promise<void>; | ||
/** | ||
* method installNodePackage | ||
* @param node_package | ||
* constructor | ||
* @param name | ||
*/ | ||
installNodePackage(node_package: string): Promise<void>; | ||
constructor(name: string); | ||
/** | ||
* method lookupInstallScript | ||
* method install | ||
* @param node_package | ||
* @param options | ||
*/ | ||
lookupInstallScript(node_package: string): Promise<string | undefined>; | ||
install(node_package: string, options: any): Promise<void>; | ||
} | ||
export declare function installPackage(node_package: string, dbManager: DBManager, dbRemote: DBRemote): Promise<void>; |
@@ -29,3 +29,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.InstallCommand = void 0; | ||
exports.installPackage = exports.InstallCommand = void 0; | ||
const Cmd_1 = require("./Cmd"); | ||
@@ -37,8 +37,14 @@ const fs = __importStar(require("fs")); | ||
const ModuleCommand_1 = require("./ModuleCommand"); | ||
const UninstallCommand_1 = require("./UninstallCommand"); | ||
const AssetCommand_1 = require("./AssetCommand"); | ||
const logger = loglevel_1.default.getLogger('InstallCommand.ts'); | ||
logger.setLevel('debug'); | ||
class InstallCommand extends Cmd_1.Cmd { | ||
/** | ||
* constructor | ||
* @param name | ||
*/ | ||
constructor(name) { | ||
super(name); | ||
this.description('npm install and upload xml modules to Cyk server') | ||
this.description('npm install and run install script') | ||
.argument('<node_package>', 'Node Package installed as dev dependency') | ||
@@ -49,47 +55,13 @@ .action(async (node_package, options) => { | ||
} | ||
/** | ||
* method install | ||
* @param node_package | ||
* @param options | ||
*/ | ||
async install(node_package, options) { | ||
try { | ||
await this.prologue(options); | ||
if (this.dbManager === undefined) | ||
throw 'dbManager undefined'; | ||
/** | ||
* install the Node Package | ||
*/ | ||
await this.installNodePackage(node_package); | ||
const installScript = await this.lookupInstallScript(node_package); | ||
if (installScript) { | ||
/** | ||
* execute installScript | ||
*/ | ||
const installPath = path.join('node_modules', node_package, 'scripts', installScript); | ||
await this.runShellCommand(installPath, []); | ||
} | ||
else { | ||
/** | ||
* default install : upload modules and execute _init.xml | ||
*/ | ||
console.log(); | ||
console.log('upload modules to server ...'); | ||
const xmlFolder = path.join('node_modules', node_package, 'xml'); | ||
if (!fs.existsSync(xmlFolder) || !fs.statSync(xmlFolder).isDirectory()) { | ||
throw 'xml folder not found ( ' + xmlFolder + ' )'; | ||
} | ||
/** | ||
* upload modules to the server | ||
*/ | ||
let initModule; | ||
const files = fs.readdirSync(xmlFolder); | ||
for (let ind = 0; ind < files.length; ind++) { | ||
const file = files[ind]; | ||
await (0, ModuleCommand_1.uploadModule)(path.join(xmlFolder, file), this.dbManager); | ||
if (file.endsWith('_init.xml')) { | ||
initModule = file; | ||
} | ||
} | ||
console.log((0, kolorist_1.green)('*') + ' upload modules to server'); | ||
if (initModule) { | ||
const initPath = path.join(xmlFolder, initModule); | ||
await this.runShellCommand('npx', ['cyk', 'run', initPath]); | ||
} | ||
} | ||
if (this.dbManager === undefined || !this.dbRemote) | ||
throw 'dbManager or dbRemote undefined'; | ||
await installPackage(node_package, this.dbManager, this.dbRemote); | ||
} | ||
@@ -100,39 +72,143 @@ catch (err) { | ||
} | ||
} | ||
exports.InstallCommand = InstallCommand; | ||
async function installPackage(node_package, dbManager, dbRemote) { | ||
/** | ||
* method installNodePackage | ||
* @param node_package | ||
* install the Node Package | ||
*/ | ||
async installNodePackage(node_package) { | ||
try { | ||
await this.runShellCommand('npm', ['install', '--save-dev', node_package]); | ||
await installNodePackage(node_package, dbManager); | ||
const installScript = await lookupInstallScript(node_package); | ||
if (installScript) { | ||
/** | ||
* execute installScript | ||
*/ | ||
const installPath = path.join('node_modules', node_package, 'scripts', installScript); | ||
await (0, Cmd_1.runShellCommand)(installPath, []); | ||
} | ||
else { | ||
/** | ||
* default install : upload modules and execute _init.xml | ||
*/ | ||
await defaultInstallScript(node_package, dbManager, dbRemote); | ||
} | ||
} | ||
exports.installPackage = installPackage; | ||
/** | ||
* method defaultInstallScript | ||
* @param node_package | ||
*/ | ||
async function defaultInstallScript(node_package, dbManager, dbRemote) { | ||
console.log(); | ||
console.log('Default install script'); | ||
/** | ||
* upload package assets | ||
*/ | ||
await uploadPackageAssets(node_package, dbManager, dbRemote); | ||
/** | ||
* upload package modules to the server | ||
*/ | ||
await uploadPackageModules(node_package, dbManager); | ||
} | ||
/** | ||
* function uploadPackageAssets | ||
* @param node_package | ||
* @param dbManager | ||
*/ | ||
async function uploadPackageAssets(node_package, dbManager, dbRemote) { | ||
const assetFolder = path.join('node_modules', node_package, 'asset'); | ||
if (!fs.existsSync(assetFolder) || !fs.statSync(assetFolder).isDirectory()) { | ||
return; | ||
} | ||
console.log(); | ||
console.log('upload assets to server ...'); | ||
if (!dbManager) | ||
throw 'dbManager undefined'; | ||
const items = fs.readdirSync(assetFolder); | ||
for (let ind = 0; ind < items.length; ind++) { | ||
const item = items[ind]; | ||
const itemPath = path.join(assetFolder, item); | ||
if (fs.statSync(itemPath).isDirectory()) { | ||
const dest = "/" + item + "/"; | ||
await (0, AssetCommand_1.uploadDirectory)(itemPath, dest, { yes: true }, dbManager, dbRemote); | ||
} | ||
catch (error) { | ||
console.error('Error installing ' + node_package + ' :', error); | ||
throw error; | ||
else { | ||
const dest = "/" + item; | ||
const fd = { path: path.join(assetFolder, item), mtime: new Date() }; | ||
await (0, AssetCommand_1.uploadAsset)(fd, dest, dbManager, dbRemote); | ||
} | ||
} | ||
/** | ||
* method lookupInstallScript | ||
* @param node_package | ||
*/ | ||
async lookupInstallScript(node_package) { | ||
let result; | ||
try { | ||
const scriptsFolder = path.join('node_modules', node_package, 'scripts'); | ||
if (fs.existsSync(scriptsFolder) && fs.statSync(scriptsFolder).isDirectory()) { | ||
const files = fs.readdirSync(scriptsFolder); | ||
for (let ind = 0; ind < files.length; ind++) { | ||
const file = files[ind]; | ||
if (file.startsWith('install.')) { | ||
result = file; | ||
} | ||
console.log((0, kolorist_1.green)('*') + ' upload assets to server'); | ||
} | ||
/** | ||
* function uploadModules | ||
* @param node_package | ||
* @param dbManager | ||
*/ | ||
async function uploadPackageModules(node_package, dbManager) { | ||
const moduleFolder = path.join('node_modules', node_package, 'module'); | ||
if (!fs.existsSync(moduleFolder) || !fs.statSync(moduleFolder).isDirectory()) { | ||
return; | ||
} | ||
console.log(); | ||
console.log('upload modules to server ...'); | ||
let initModule; | ||
const files = fs.readdirSync(moduleFolder); | ||
for (let ind = 0; ind < files.length; ind++) { | ||
const file = files[ind]; | ||
if (!dbManager) | ||
throw 'dbManager undefined'; | ||
await (0, ModuleCommand_1.uploadModule)(path.join(moduleFolder, file), dbManager); | ||
if (file.endsWith('_init.xml')) { | ||
initModule = file; | ||
} | ||
} | ||
console.log((0, kolorist_1.green)('*') + ' upload modules to server'); | ||
if (initModule) { | ||
const initPath = path.join(moduleFolder, initModule); | ||
await (0, Cmd_1.runShellCommand)('npx', ['cyk', 'run', initPath]); | ||
} | ||
} | ||
/** | ||
* method installNodePackage | ||
* @param node_package | ||
*/ | ||
async function installNodePackage(node_package, dbManager) { | ||
try { | ||
const packageJson = await (0, Cmd_1.readPackageJson)(); | ||
if (packageJson.devDependencies && packageJson.devDependencies[node_package] | ||
|| packageJson.dependencies && packageJson.dependencies[node_package]) { | ||
console.log(node_package + ' already installed. We uninstall it first'); | ||
if (!dbManager) | ||
throw 'dbManager undefined'; | ||
await (0, UninstallCommand_1.uninstallPackage)(node_package, dbManager); | ||
} | ||
await (0, Cmd_1.runShellCommand)('npm', ['install', '--save-dev', node_package]); | ||
} | ||
catch (error) { | ||
console.error('Error installing ' + node_package + ' :', error); | ||
throw error; | ||
} | ||
} | ||
/** | ||
* function lookupInstallScript | ||
* @param node_package | ||
*/ | ||
async function lookupInstallScript(node_package) { | ||
let result; | ||
try { | ||
const scriptsFolder = path.join('node_modules', node_package, 'scripts'); | ||
if (fs.existsSync(scriptsFolder) && fs.statSync(scriptsFolder).isDirectory()) { | ||
const files = fs.readdirSync(scriptsFolder); | ||
for (let ind = 0; ind < files.length; ind++) { | ||
const file = files[ind]; | ||
if (file.startsWith('install.')) { | ||
result = file; | ||
} | ||
} | ||
return result; | ||
} | ||
catch (err) { | ||
throw err; | ||
} | ||
return result; | ||
} | ||
catch (err) { | ||
throw err; | ||
} | ||
} | ||
exports.InstallCommand = InstallCommand; |
@@ -13,1 +13,7 @@ #!/usr/bin/env ts-node | ||
export declare function uploadModule(file: string, dbManager: DBManager): Promise<void>; | ||
/** | ||
* function deleteModule | ||
* @param dbname | ||
* @param dbManager | ||
*/ | ||
export declare function deleteModule(dbname: string, dbManager: DBManager): Promise<void>; |
@@ -30,3 +30,3 @@ #!/usr/bin/env ts-node | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.uploadModule = exports.ModuleCommand = void 0; | ||
exports.deleteModule = exports.uploadModule = exports.ModuleCommand = void 0; | ||
const core_1 = require("@cyklang/core"); | ||
@@ -170,2 +170,3 @@ const fs = __importStar(require("fs")); | ||
else { | ||
logger.debug('module exists : ' + dbModuleExist.dbname + ', id ' + dbModuleExist.id); | ||
// update | ||
@@ -285,1 +286,11 @@ dbModuleExist.source = source; | ||
} | ||
/** | ||
* function deleteModule | ||
* @param dbname | ||
* @param dbManager | ||
*/ | ||
async function deleteModule(dbname, dbManager) { | ||
const dbClient = new DBClient_1.DBClient(dbManager); | ||
await dbClient.deleteModule(dbname); | ||
} | ||
exports.deleteModule = deleteModule; |
{ | ||
"name": "@cyklang/cli", | ||
"version": "0.5.4", | ||
"version": "0.5.5", | ||
"description": "cyklang CLI", | ||
@@ -20,3 +20,3 @@ "main": "build/index.js", | ||
"dependencies": { | ||
"@cyklang/core": "^0.5.2", | ||
"@cyklang/core": "^0.5.3", | ||
"commander": "^9.4.0", | ||
@@ -23,0 +23,0 @@ "dotenv": "^16.0.1", |
@@ -10,3 +10,3 @@ import { Command } from "commander" | ||
// import readline from 'readline' | ||
import { DBAsset, DBExecuteRequest, DBManager, ObjectData, parseXML, PrimitiveData } from "@cyklang/core" | ||
import { DBAsset, DBExecuteRequest, DBManager, DBRemote, ObjectData, parseXML, PrimitiveData } from "@cyklang/core" | ||
import FormData from 'form-data' | ||
@@ -116,3 +116,3 @@ | ||
await this.prologue(options) | ||
if (! this.dbManager) throw 'dbManager undefined' | ||
if (!this.dbManager) throw 'dbManager undefined' | ||
const dbClient = new DBClient(this.dbManager) | ||
@@ -126,5 +126,5 @@ const list = await dbClient.selectFromTable('Assets to delete', 'cyk_asset', | ||
); | ||
const reply = await inquirer.prompt({type: 'confirm', name: 'confirm', message: 'Do you want to delete these ' + list.length + ' file(s)'}) | ||
const reply = await inquirer.prompt({ type: 'confirm', name: 'confirm', message: 'Do you want to delete these ' + list.length + ' file(s)' }) | ||
if (reply.confirm) { | ||
for(let ind = 0; ind < list.length; ind++) { | ||
for (let ind = 0; ind < list.length; ind++) { | ||
const asset = list[ind] | ||
@@ -174,3 +174,3 @@ logger.info('delete ' + asset.asset_route) | ||
interface FileDescriptor { | ||
export interface FileDescriptor { | ||
path: string | ||
@@ -200,13 +200,4 @@ mtime: Date | ||
mimetypeLookup(filename: string): string | false { | ||
let result: string | false | ||
if (path.extname(filename) === '.cyk') { | ||
result = 'application/xml' | ||
} | ||
else { | ||
result = mime.lookup(filename) | ||
} | ||
return result | ||
} | ||
/** | ||
@@ -279,3 +270,3 @@ * method commandU | ||
if (options.clean) { | ||
await this.cleanDestination(dest) | ||
await cleanDestination(dest, this.dbManager, this.dbRemote) | ||
} | ||
@@ -288,3 +279,3 @@ | ||
if (filestat.isDirectory() === true) { | ||
await this.uploadDirectory(source, dest, options) | ||
await uploadDirectory(source, dest, options, this.dbManager, this.dbRemote) | ||
} | ||
@@ -294,3 +285,3 @@ else if (filestat.isFile() === true) { | ||
logger.debug('upload file ' + source + ' to ' + dest + base) | ||
await this.uploadAsset({ path: source, mtime: filestat.mtime }, dest + base, options.auth) | ||
await uploadAsset({ path: source, mtime: filestat.mtime }, dest + base, this.dbManager, this.dbRemote, options.auth) | ||
} | ||
@@ -303,210 +294,234 @@ } | ||
} | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// cleanDestination | ||
//---------------------------------------------------------------------------------------------- | ||
/** | ||
* function cleanDestination | ||
* @param dest | ||
* @param dbManager | ||
* @param dbRemote | ||
*/ | ||
async function cleanDestination(dest: string, dbManager: DBManager | undefined, dbRemote: DBRemote | undefined) { | ||
async cleanDestination(dest: string) { | ||
const remoteList = await scanAssets(this.dbManager) | ||
for (let ind = 0; ind < remoteList.length; ind++) { | ||
const fd = remoteList[ind] | ||
if (fd.path.startsWith(dest)) { | ||
const url = '/api/admin/assets/' + fd.id | ||
await this.dbRemote?.apiServer.delete(url) | ||
} | ||
const remoteList = await scanAssets(dbManager) | ||
for (let ind = 0; ind < remoteList.length; ind++) { | ||
const fd = remoteList[ind] | ||
if (fd.path.startsWith(dest)) { | ||
const url = '/api/admin/assets/' + fd.id | ||
await dbRemote?.apiServer.delete(url) | ||
} | ||
} | ||
} | ||
/** | ||
* function uploadDirectory | ||
* @param source | ||
* @param dest | ||
* @param options {yes: no confirmation, auth: basic/token/cookie/undefined} | ||
* @param dbManager | ||
* @param dbRemote | ||
*/ | ||
export async function uploadDirectory(source: string, dest: string, options: any, | ||
dbManager: DBManager | undefined, dbRemote: DBRemote | undefined) { | ||
//---------------------------------------------------------------------------------------------- | ||
// uploadDirectory | ||
//---------------------------------------------------------------------------------------------- | ||
const localList: FileDescriptor[] = [] | ||
let dirName: string | ||
if (source.substring(source.length - 1) === '/') { | ||
// trailing directory separator | ||
dirName = source | ||
} | ||
else { | ||
dirName = source + '/' | ||
} | ||
async uploadDirectory(source: string, dest: string, options: any) { | ||
// logger.debug('options', options) | ||
const localList: FileDescriptor[] = [] | ||
let dirName: string | ||
if (source.substring(source.length - 1) === '/') { | ||
// trailing directory separator | ||
dirName = source | ||
} | ||
else { | ||
dirName = source + '/' | ||
} | ||
scanDir(dirName, localList) | ||
// logger.debug('options', options) | ||
const remoteList = await scanAssets(dbManager) | ||
this.scanDir(dirName, localList) | ||
const uploadList = buildUploadList(dirName, dest, localList, remoteList) | ||
const remoteList = await scanAssets(this.dbManager) | ||
// logger.info(fileNames.join('\n')) | ||
if (uploadList.length === 0) throw 'None file to upload' | ||
const uploadList = this.buildUploadList(dirName, dest, localList, remoteList) | ||
let uploadConfirmed = (options.yes !== undefined) | ||
// logger.info(fileNames.join('\n')) | ||
if (uploadList.length === 0) throw 'None file to upload' | ||
if (uploadConfirmed === false) { | ||
const reply = await inquirer.prompt({ type: 'confirm', name: 'confirm', message: 'Do you want to upload this(these) ' + uploadList.length + ' file(s) ?' }) | ||
if (reply.confirm === true) uploadConfirmed = true | ||
} | ||
let uploadConfirmed = (options.yes !== undefined) | ||
if (uploadConfirmed === true) { | ||
await uploadFiles(dirName, uploadList, dest, dbManager, dbRemote, options.auth) | ||
} | ||
} | ||
/** | ||
* function buildUploadList | ||
* @param dirName | ||
* @param dest | ||
* @param localList | ||
* @param remoteList | ||
* @returns | ||
*/ | ||
function buildUploadList(dirName: string, dest: string, localList: FileDescriptor[], remoteList: FileDescriptor[]): FileDescriptor[] { | ||
const result: FileDescriptor[] = [] | ||
const remoteMap = new Map<string, FileDescriptor>() | ||
for (let ind = 0; ind < remoteList.length; ind++) { | ||
const remote = remoteList[ind] | ||
remoteMap.set(remote.path, remote) | ||
} | ||
for (let ind = 0; ind < localList.length; ind++) { | ||
const localDesc = localList[ind] | ||
const route = dest + localDesc.path.substring(dirName.length) | ||
const remoteDesc = remoteMap.get(route) | ||
if (uploadConfirmed === false) { | ||
const reply = await inquirer.prompt({ type: 'confirm', name: 'confirm', message: 'Do you want to upload this(these) ' + uploadList.length + ' file(s) ?' }) | ||
if (reply.confirm === true) uploadConfirmed = true | ||
if (remoteDesc === undefined || remoteDesc.mtime.getTime() + 1000 < localDesc.mtime.getTime()) { | ||
if (remoteDesc === undefined) logger.debug('remoteDesc undefined') | ||
else logger.debug('remoteDesc.mtime ' + remoteDesc.mtime.getTime(), 'localDesc.mtime ' + localDesc.mtime.getTime()) | ||
logger.info(localDesc.path) | ||
result.push(localDesc) | ||
} | ||
if (uploadConfirmed === true) { | ||
await this.uploadFiles(dirName, uploadList, dest, options.auth) | ||
} | ||
// const rl = readline.createInterface(process.stdin, process.stdout) | ||
// rl.question('Do you want to upload this(these) ' + uploadList.length + ' file(s) (Y/N/y/n) ?', async (reply) => { | ||
// rl.close() | ||
// if (reply !== 'Y' && reply !== 'y') { | ||
// logger.info('upload cancelled') | ||
// return | ||
// } | ||
// await this.uploadFiles(dirName, uploadList, dest) | ||
// }) | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// buildUploadList | ||
//---------------------------------------------------------------------------------------------- | ||
buildUploadList(dirName: string, dest: string, localList: FileDescriptor[], remoteList: FileDescriptor[]): FileDescriptor[] { | ||
const result: FileDescriptor[] = [] | ||
const remoteMap = new Map<string, FileDescriptor>() | ||
for (let ind = 0; ind < remoteList.length; ind++) { | ||
const remote = remoteList[ind] | ||
remoteMap.set(remote.path, remote) | ||
return result | ||
} | ||
/** | ||
* function scanDir | ||
* @param dirName | ||
* @param result | ||
*/ | ||
function scanDir(dirName: string, result: FileDescriptor[]) { | ||
const files = fs.readdirSync(dirName) | ||
for (let ind = 0; ind < files.length; ind++) { | ||
const fileName = files[ind] | ||
if (file2exclude(fileName) === true) continue | ||
const fstat = fs.statSync(dirName + fileName) | ||
if (fstat.isDirectory() === true) { | ||
scanDir(dirName + fileName + '/', result) | ||
} | ||
for (let ind = 0; ind < localList.length; ind++) { | ||
const localDesc = localList[ind] | ||
const route = dest + localDesc.path.substring(dirName.length) | ||
const remoteDesc = remoteMap.get(route) | ||
if (remoteDesc === undefined || remoteDesc.mtime.getTime() + 1000 < localDesc.mtime.getTime()) { | ||
if (remoteDesc === undefined) logger.debug('remoteDesc undefined') | ||
else logger.debug('remoteDesc.mtime ' + remoteDesc.mtime.getTime(), 'localDesc.mtime ' + localDesc.mtime.getTime()) | ||
logger.info(localDesc.path) | ||
result.push(localDesc) | ||
else { | ||
if (mimetypeLookup(fileName) === false) { | ||
logger.info(fileName + ' file extension is unknown and will not be uploaded') | ||
continue | ||
} | ||
//const dbAssetExist = this.dbManager?.dbAssetExist() | ||
result.push({ path: dirName + fileName, mtime: fstat.mtime }) | ||
// logger.debug(dirName + '/' + fileName) | ||
} | ||
return result | ||
} | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// scanDir | ||
//---------------------------------------------------------------------------------------------- | ||
scanDir(dirName: string, result: FileDescriptor[]) { | ||
const files = fs.readdirSync(dirName) | ||
for (let ind = 0; ind < files.length; ind++) { | ||
const fileName = files[ind] | ||
if (this.file2exclude(fileName) === true) continue | ||
const fstat = fs.statSync(dirName + fileName) | ||
if (fstat.isDirectory() === true) { | ||
this.scanDir(dirName + fileName + '/', result) | ||
} | ||
else { | ||
if (this.mimetypeLookup(fileName) === false) { | ||
logger.info(fileName + ' file extension is unknown and will not be uploaded') | ||
continue | ||
} | ||
//const dbAssetExist = this.dbManager?.dbAssetExist() | ||
result.push({ path: dirName + fileName, mtime: fstat.mtime }) | ||
// logger.debug(dirName + '/' + fileName) | ||
} | ||
} | ||
const ignorePatterns = ['.git', 'node_modules'] | ||
/** | ||
* function file2exclude | ||
* @param fileName | ||
* @returns | ||
*/ | ||
function file2exclude(fileName: string): boolean { | ||
let result = false | ||
ignorePatterns.forEach((pattern) => { | ||
if (fileName === pattern) result = true | ||
}) | ||
return result | ||
} | ||
/** | ||
* function uploadFiles | ||
* @param dirName | ||
* @param uploadList | ||
* @param dest | ||
* @param dbManager | ||
* @param dbRemote | ||
* @param auth | ||
*/ | ||
async function uploadFiles(dirName: string, uploadList: FileDescriptor[], dest: string, dbManager: DBManager | undefined, dbRemote: DBRemote | undefined, auth: string | undefined) { | ||
for (let ind = 0; ind < uploadList.length; ind++) { | ||
const upload = uploadList[ind] | ||
const route = dest + upload.path.substring(dirName.length) | ||
logger.debug('upload ' + upload.path + ' to ' + route) | ||
await uploadAsset(upload, route, dbManager, dbRemote, auth) | ||
} | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// file2exclude | ||
//---------------------------------------------------------------------------------------------- | ||
/** | ||
* function uploadAsset | ||
* @param upload | ||
* @param route | ||
* @param dbManager | ||
* @param dbRemote | ||
* @param auth | ||
*/ | ||
export async function uploadAsset(upload: FileDescriptor, route: string, dbManager: DBManager | undefined, dbRemote: DBRemote | undefined, auth?: string) { | ||
// logger.debug('uploadAsset ' + upload.path + ' to route ' + route + ' with mimetype ' + this.mimetypeLookup(upload.path) + ', auth : ' + auth) | ||
ignorePatterns = ['.git', 'node_modules'] | ||
file2exclude(fileName: string): boolean { | ||
let result = false | ||
this.ignorePatterns.forEach((pattern) => { | ||
if (fileName === pattern) result = true | ||
}) | ||
return result | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// uploadFiles | ||
//---------------------------------------------------------------------------------------------- | ||
async uploadFiles(dirName: string, uploadList: FileDescriptor[], dest: string, auth: string | undefined) { | ||
for (let ind = 0; ind < uploadList.length; ind++) { | ||
const upload = uploadList[ind] | ||
const route = dest + upload.path.substring(dirName.length) | ||
logger.debug('upload ' + upload.path + ' to ' + route) | ||
await this.uploadAsset(upload, route, auth) | ||
try { | ||
let dbAsset: DBAsset | undefined = await dbManager?.dbAssetExist(route) | ||
if (dbAsset === undefined) { | ||
dbAsset = new DBAsset() | ||
} | ||
} | ||
const mimetype = mimetypeLookup(upload.path) | ||
if (mimetype === false) throw 'mimetype false for ' + upload | ||
dbAsset.mimetype = mimetype | ||
dbAsset.route = route | ||
dbAsset.auth = auth | ||
if (dbAsset.auth === 'none') dbAsset.auth = undefined | ||
//---------------------------------------------------------------------------------------------- | ||
// uploadAsset | ||
//---------------------------------------------------------------------------------------------- | ||
// const fstat = fs.statSync(fileName) | ||
dbAsset.last_update = upload.mtime | ||
async uploadAsset(upload: FileDescriptor, route: string, auth?: string) { | ||
// logger.debug('uploadAsset ' + upload.path + ' to route ' + route + ' with mimetype ' + this.mimetypeLookup(upload.path) + ', auth : ' + auth) | ||
// const contentBuffer = fs.readFileSync(fileName) | ||
// dbAsset.content = contentBuffer | ||
// logger.debug('dbAsset.content length ' + dbAsset.content.length) | ||
try { | ||
let dbAsset: DBAsset | undefined = await this.dbManager?.dbAssetExist(route) | ||
if (dbAsset === undefined) { | ||
dbAsset = new DBAsset() | ||
} | ||
const mimetype = this.mimetypeLookup(upload.path) | ||
if (mimetype === false) throw 'mimetype false for ' + upload | ||
dbAsset.mimetype = mimetype | ||
dbAsset.route = route | ||
dbAsset.auth = auth | ||
if (dbAsset.auth === 'none') dbAsset.auth = undefined | ||
// const fstat = fs.statSync(fileName) | ||
dbAsset.last_update = upload.mtime | ||
// const contentBuffer = fs.readFileSync(fileName) | ||
// dbAsset.content = contentBuffer | ||
// logger.debug('dbAsset.content length ' + dbAsset.content.length) | ||
if (dbAsset.id === undefined) { | ||
dbAsset.id = await this.dbManager?.dbAssetInsert(dbAsset) | ||
logger.info('inserted asset ' + dbAsset.id + ' route ' + dbAsset.route) | ||
} | ||
else { | ||
await this.dbManager?.dbAssetUpdate(dbAsset) | ||
logger.info('updated asset ' + dbAsset.route) | ||
} | ||
await this.uploadAssetContent(dbAsset, upload.path) | ||
if (dbAsset.id === undefined) { | ||
dbAsset.id = await dbManager?.dbAssetInsert(dbAsset) | ||
logger.info('inserted asset ' + dbAsset.id + ' route ' + dbAsset.route) | ||
} | ||
catch (err) { | ||
logger.error(err) | ||
else { | ||
await dbManager?.dbAssetUpdate(dbAsset) | ||
logger.info('updated asset ' + dbAsset.route) | ||
} | ||
await uploadAssetContent(dbAsset, upload.path, dbRemote) | ||
} | ||
catch (err) { | ||
logger.error(err) | ||
} | ||
} | ||
//---------------------------------------------------------------------------------------------- | ||
// uploadAssetContent | ||
//---------------------------------------------------------------------------------------------- | ||
/** | ||
* function mimetypeLookup | ||
* @param filename | ||
* @returns | ||
*/ | ||
function mimetypeLookup(filename: string): string | false { | ||
let result: string | false | ||
if (path.extname(filename) === '.cyk') { | ||
result = 'application/xml' | ||
} | ||
else { | ||
result = mime.lookup(filename) | ||
} | ||
return result | ||
} | ||
async uploadAssetContent(dbAsset: DBAsset, fileName: string) { | ||
logger.debug('uploadAssetContent file ' + fileName + ' to path ' + path) | ||
try { | ||
const file = fs.createReadStream(fileName) | ||
const form = new FormData() | ||
form.append('uploadFile', file) | ||
/** | ||
* function uploadAssetContent | ||
* @param dbAsset | ||
* @param fileName | ||
* @param dbRemote | ||
*/ | ||
async function uploadAssetContent(dbAsset: DBAsset, fileName: string, dbRemote: DBRemote | undefined) { | ||
logger.debug('uploadAssetContent file ' + fileName + ' to path ' + path) | ||
try { | ||
const file = fs.createReadStream(fileName) | ||
const form = new FormData() | ||
form.append('uploadFile', file) | ||
const route = '/api/upload/cyk_asset/asset_content?asset_id=' + dbAsset.id | ||
const resp = await this.dbRemote?.apiServer.post(route, form) | ||
if (resp.status === 200) { | ||
logger.info(fileName + ' uploaded') | ||
} | ||
const route = '/api/upload/cyk_asset/asset_content?asset_id=' + dbAsset.id | ||
const resp = await dbRemote?.apiServer.post(route, form) | ||
if (resp.status === 200) { | ||
logger.info(fileName + ' uploaded') | ||
} | ||
catch (err) { | ||
logger.error(err) | ||
} | ||
} | ||
catch (err) { | ||
logger.error(err) | ||
} | ||
} |
@@ -8,3 +8,4 @@ import { DBManager, DBRemote, SigninResponse, Structure } from "@cyklang/core"; | ||
import { exec, spawn } from 'child_process'; | ||
import {red, green, bold} from 'kolorist' | ||
import { red, green, bold } from 'kolorist' | ||
import * as fs from 'fs' | ||
@@ -119,42 +120,62 @@ const logger = loglevel.getLogger('Cmd.ts') | ||
/** | ||
* method runShellCommand | ||
* @param command | ||
*/ | ||
async runShellCommand(command: string, args: string[]) { | ||
try { | ||
await this.spawnCommand(command, args) | ||
// console.log(command) | ||
// const result = await this.executeCommand(command); | ||
// console.log(result.stdout); | ||
// if (result.stderr && result.stderr.trim() !== '') | ||
// console.error(result.stderr); | ||
} catch (error) { | ||
console.error('Error running "' + command + '":', error); | ||
throw error | ||
} | ||
} | ||
/** | ||
* method runShellCommand | ||
* @param command | ||
*/ | ||
export async function runShellCommand(command: string, args: string[]) { | ||
try { | ||
await spawnCommand(command, args) | ||
// console.log(command) | ||
// const result = await this.executeCommand(command); | ||
// console.log(result.stdout); | ||
// if (result.stderr && result.stderr.trim() !== '') | ||
// console.error(result.stderr); | ||
} catch (error) { | ||
console.error('Error running "' + command + '":', error); | ||
throw error | ||
} | ||
} | ||
/** | ||
* | ||
* @param command | ||
* @param args | ||
* @returns | ||
*/ | ||
spawnCommand(command: string, args: string[]): Promise<void> { | ||
console.log() | ||
console.log([command, ...args, '...'].join(' ')) | ||
const child_process = spawn(command, args, { stdio: 'inherit' }) | ||
return new Promise((resolve, reject) => { | ||
child_process.on('close', (code) => { | ||
if (code === 0) { | ||
console.log(green('*') + ' ' + [command, ...args].join(' ')) | ||
resolve() | ||
} | ||
else { | ||
reject(new Error([command, ...args].join(' ') + ' --> Error ' + code)) | ||
} | ||
}) | ||
/** | ||
* function spawnCommand | ||
* @param command | ||
* @param args | ||
* @returns | ||
*/ | ||
export function spawnCommand(command: string, args: string[]): Promise<void> { | ||
console.log() | ||
console.log([command, ...args, '...'].join(' ')) | ||
const child_process = spawn(command, args, { stdio: 'inherit' }) | ||
return new Promise((resolve, reject) => { | ||
child_process.on('close', (code) => { | ||
if (code === 0) { | ||
console.log(green('*') + ' ' + [command, ...args].join(' ')) | ||
resolve() | ||
} | ||
else { | ||
reject(new Error([command, ...args].join(' ') + ' --> Error ' + code)) | ||
} | ||
}) | ||
}) | ||
} | ||
/** | ||
* function readPackageJson | ||
* @returns | ||
*/ | ||
export async function readPackageJson(): Promise<any> { | ||
try { | ||
if (!fs.existsSync("package.json")) throw 'package.json not found' | ||
const fileContent = fs.readFileSync("package.json") | ||
return JSON.parse(fileContent.toString()) | ||
} | ||
catch (err) { | ||
console.error(err) | ||
throw err | ||
} | ||
} |
@@ -138,2 +138,3 @@ import { BasicType, DBColumn, DBExecuteRequest, DBManager, DBTable, ObjectData, parseXML, PrimitiveData, Script, variable2json, XmlError } from "@cyklang/core"; | ||
await this.dbManager.dbModuleDelete(dbModule) | ||
logger.info('module ' + dbname + ' (id ' + dbModule.id + ' deleted)') | ||
} | ||
@@ -140,0 +141,0 @@ catch (err) { |
@@ -13,2 +13,3 @@ #!/usr/bin/env node | ||
import { OpenCommand } from './OpenCommand' | ||
import { UninstallCommand } from './UninstallCommand' | ||
const logger = loglevel.getLogger("index.ts") | ||
@@ -19,6 +20,7 @@ logger.setLevel("debug") | ||
program.name('cyk').description('cyklang CLI') | ||
.version('0.5.4') | ||
.version('0.5.5') | ||
program.addCommand(new InstallCommand('install')) | ||
program.addCommand(new InstallCommand('i')) | ||
program.addCommand(new UninstallCommand('uninstall')) | ||
program.addCommand(new AssetCommand('asset', 'manage assets')) | ||
@@ -25,0 +27,0 @@ program.addCommand(new AssetCommand('a', 'manage assets')) |
@@ -1,8 +0,11 @@ | ||
import { Cmd } from "./Cmd"; | ||
import { Cmd, readPackageJson, runShellCommand } from "./Cmd"; | ||
import * as fs from "fs" | ||
import * as path from "path" | ||
import {green, red, bold} from 'kolorist' | ||
import { green, red, bold } from 'kolorist' | ||
import loglevel from 'loglevel' | ||
import { uploadModule } from "./ModuleCommand"; | ||
import { uninstallPackage } from "./UninstallCommand"; | ||
import { DBManager, DBRemote } from "@cyklang/core"; | ||
import { FileDescriptor, uploadAsset, uploadDirectory } from "./AssetCommand"; | ||
const logger = loglevel.getLogger('InstallCommand.ts') | ||
@@ -12,5 +15,9 @@ logger.setLevel('debug') | ||
export class InstallCommand extends Cmd { | ||
/** | ||
* constructor | ||
* @param name | ||
*/ | ||
constructor(name: string) { | ||
super(name) | ||
this.description('npm install and upload xml modules to Cyk server') | ||
this.description('npm install and run install script') | ||
.argument('<node_package>', 'Node Package installed as dev dependency') | ||
@@ -22,50 +29,13 @@ .action(async (node_package: any, options: any) => { | ||
/** | ||
* method install | ||
* @param node_package | ||
* @param options | ||
*/ | ||
async install(node_package: string, options: any) { | ||
try { | ||
await this.prologue(options) | ||
if (this.dbManager === undefined) throw 'dbManager undefined' | ||
if (this.dbManager === undefined || !this.dbRemote) throw 'dbManager or dbRemote undefined' | ||
/** | ||
* install the Node Package | ||
*/ | ||
await this.installNodePackage(node_package) | ||
const installScript = await this.lookupInstallScript(node_package) | ||
if (installScript) { | ||
/** | ||
* execute installScript | ||
*/ | ||
const installPath = path.join('node_modules',node_package,'scripts',installScript) | ||
await this.runShellCommand(installPath, []) | ||
} | ||
else { | ||
/** | ||
* default install : upload modules and execute _init.xml | ||
*/ | ||
console.log() | ||
console.log('upload modules to server ...') | ||
const xmlFolder = path.join('node_modules', node_package, 'xml') | ||
if (!fs.existsSync(xmlFolder) || !fs.statSync(xmlFolder).isDirectory()) { | ||
throw 'xml folder not found ( ' + xmlFolder + ' )' | ||
} | ||
/** | ||
* upload modules to the server | ||
*/ | ||
let initModule: string | undefined | ||
const files = fs.readdirSync(xmlFolder) | ||
for (let ind = 0; ind < files.length; ind++) { | ||
const file = files[ind] | ||
await uploadModule(path.join(xmlFolder, file), this.dbManager) | ||
if (file.endsWith('_init.xml')) { | ||
initModule = file | ||
} | ||
} | ||
console.log(green('*') + ' upload modules to server' ) | ||
if (initModule) { | ||
const initPath = path.join(xmlFolder, initModule) | ||
await this.runShellCommand('npx', ['cyk', 'run', initPath]) | ||
} | ||
} | ||
await installPackage(node_package, this.dbManager, this.dbRemote) | ||
} | ||
@@ -76,41 +46,153 @@ catch (err) { | ||
} | ||
} | ||
export async function installPackage(node_package: string, dbManager: DBManager, dbRemote: DBRemote) { | ||
/** | ||
* method installNodePackage | ||
* @param node_package | ||
* install the Node Package | ||
*/ | ||
async installNodePackage(node_package: string) { | ||
await installNodePackage(node_package, dbManager) | ||
try { | ||
await this.runShellCommand('npm', ['install', '--save-dev', node_package]) | ||
} catch (error) { | ||
console.error('Error installing ' + node_package + ' :', error); | ||
throw error | ||
} | ||
const installScript = await lookupInstallScript(node_package) | ||
if (installScript) { | ||
/** | ||
* execute installScript | ||
*/ | ||
const installPath = path.join('node_modules', node_package, 'scripts', installScript) | ||
await runShellCommand(installPath, []) | ||
} | ||
else { | ||
/** | ||
* default install : upload modules and execute _init.xml | ||
*/ | ||
await defaultInstallScript(node_package, dbManager, dbRemote) | ||
} | ||
} | ||
/** | ||
* method defaultInstallScript | ||
* @param node_package | ||
*/ | ||
async function defaultInstallScript(node_package: string, dbManager: DBManager, dbRemote: DBRemote) { | ||
console.log() | ||
console.log('Default install script') | ||
/** | ||
* method lookupInstallScript | ||
* @param node_package | ||
* upload package assets | ||
*/ | ||
async lookupInstallScript(node_package: string): Promise<string | undefined> { | ||
let result: string | undefined | ||
try { | ||
const scriptsFolder = path.join('node_modules', node_package, 'scripts') | ||
if (fs.existsSync(scriptsFolder) && fs.statSync(scriptsFolder).isDirectory()) { | ||
const files = fs.readdirSync(scriptsFolder) | ||
for (let ind = 0; ind < files.length; ind++) { | ||
const file = files[ind] | ||
if (file.startsWith('install.')) { | ||
result = file | ||
} | ||
await uploadPackageAssets(node_package, dbManager, dbRemote) | ||
/** | ||
* upload package modules to the server | ||
*/ | ||
await uploadPackageModules(node_package, dbManager) | ||
} | ||
/** | ||
* function uploadPackageAssets | ||
* @param node_package | ||
* @param dbManager | ||
*/ | ||
async function uploadPackageAssets(node_package: string, dbManager: DBManager, dbRemote: DBRemote) { | ||
const assetFolder = path.join('node_modules', node_package, 'asset') | ||
if (!fs.existsSync(assetFolder) || !fs.statSync(assetFolder).isDirectory()) { | ||
return | ||
} | ||
console.log() | ||
console.log('upload assets to server ...') | ||
if (!dbManager) throw 'dbManager undefined' | ||
const items = fs.readdirSync(assetFolder) | ||
for (let ind = 0; ind < items.length; ind++) { | ||
const item = items[ind] | ||
const itemPath = path.join(assetFolder, item) | ||
if (fs.statSync(itemPath).isDirectory()) { | ||
const dest = "/" + item + "/" | ||
await uploadDirectory(itemPath, dest, {yes: true}, dbManager, dbRemote) | ||
} | ||
else { | ||
const dest = "/" + item | ||
const fd: FileDescriptor = {path: path.join(assetFolder, item), mtime: new Date()} | ||
await uploadAsset(fd, dest, dbManager, dbRemote) | ||
} | ||
} | ||
console.log(green('*') + ' upload assets to server') | ||
} | ||
/** | ||
* function uploadModules | ||
* @param node_package | ||
* @param dbManager | ||
*/ | ||
async function uploadPackageModules(node_package: string, dbManager: DBManager) { | ||
const moduleFolder = path.join('node_modules', node_package, 'module') | ||
if (!fs.existsSync(moduleFolder) || !fs.statSync(moduleFolder).isDirectory()) { | ||
return | ||
} | ||
console.log() | ||
console.log('upload modules to server ...') | ||
let initModule: string | undefined | ||
const files = fs.readdirSync(moduleFolder) | ||
for (let ind = 0; ind < files.length; ind++) { | ||
const file = files[ind] | ||
if (!dbManager) throw 'dbManager undefined' | ||
await uploadModule(path.join(moduleFolder, file), dbManager) | ||
if (file.endsWith('_init.xml')) { | ||
initModule = file | ||
} | ||
} | ||
console.log(green('*') + ' upload modules to server') | ||
if (initModule) { | ||
const initPath = path.join(moduleFolder, initModule) | ||
await runShellCommand('npx', ['cyk', 'run', initPath]) | ||
} | ||
} | ||
/** | ||
* method installNodePackage | ||
* @param node_package | ||
*/ | ||
async function installNodePackage(node_package: string, dbManager: DBManager) { | ||
try { | ||
const packageJson = await readPackageJson() | ||
if (packageJson.devDependencies && packageJson.devDependencies[node_package] | ||
|| packageJson.dependencies && packageJson.dependencies[node_package]) { | ||
console.log(node_package + ' already installed. We uninstall it first') | ||
if (!dbManager) throw 'dbManager undefined' | ||
await uninstallPackage(node_package, dbManager) | ||
} | ||
await runShellCommand('npm', ['install', '--save-dev', node_package]) | ||
} catch (error) { | ||
console.error('Error installing ' + node_package + ' :', error); | ||
throw error | ||
} | ||
} | ||
/** | ||
* function lookupInstallScript | ||
* @param node_package | ||
*/ | ||
async function lookupInstallScript(node_package: string): Promise<string | undefined> { | ||
let result: string | undefined | ||
try { | ||
const scriptsFolder = path.join('node_modules', node_package, 'scripts') | ||
if (fs.existsSync(scriptsFolder) && fs.statSync(scriptsFolder).isDirectory()) { | ||
const files = fs.readdirSync(scriptsFolder) | ||
for (let ind = 0; ind < files.length; ind++) { | ||
const file = files[ind] | ||
if (file.startsWith('install.')) { | ||
result = file | ||
} | ||
} | ||
return result | ||
} | ||
catch (err) { | ||
throw err | ||
} | ||
return result | ||
} | ||
catch (err) { | ||
throw err | ||
} | ||
} |
@@ -150,2 +150,3 @@ #!/usr/bin/env ts-node | ||
else { | ||
logger.debug('module exists : ' + dbModuleExist.dbname + ', id ' + dbModuleExist.id) | ||
// update | ||
@@ -277,1 +278,12 @@ dbModuleExist.source = source | ||
/** | ||
* function deleteModule | ||
* @param dbname | ||
* @param dbManager | ||
*/ | ||
export async function deleteModule(dbname: string, dbManager: DBManager) { | ||
const dbClient = new DBClient(dbManager) | ||
await dbClient.deleteModule(dbname) | ||
} | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
399732
124
6502
56
Updated@cyklang/core@^0.5.3