diff --git a/README.md b/README.md index 12502b5..88371ad 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ digital equivalent of placing a physical protective sign. Note that this utility only processes *cultural* heritage sites, because Whiteflag (currently) only defines a message (`P52`) that corresponds with the -protective sign for cultural property i.a.w. [the 1954 Hague Convention](http://www.unesco.org/new/en/culture/themes/armed-conflict-and-heritage/convention-and-protocols/1954-hague-convention/). +protective sign for cultural property i.a.w. [the 1954 Hague Convention](http://www.unesco.org/new/en/culture/themes/armed-conflict-and-heritage/convention-and-protocols/1954-hague-convention/). The `P52` protective sign message is followed by an `R1(3)` resource message with an URL linking the protective sign to the corresponding WHL entry. This utility is for technology development, test and evaluation purposes only. This means that it is a tool in support of testing the Whiteflag protocol, but @@ -58,18 +58,16 @@ wfwhl [-s ...] [-w |-f ] The main options are the following: -* `-s`, `--sites` : Specify the world heritage site(s) to be processed by \ number; multiple sites may be specified. If no sites are specified, all sites are processed. +* `-s`, `--sites` : Specifies the world heritage site(s) by \ number; multiple sites may be specified. If no sites are specified, all sites are processed. * `-w`, `--web` : The source \ of the WHL in XML on the web. If not specified the default is `https://whc.unesco.org/en/list/xml/`. Cannot be used with `-f`. * `-f`, `--file` : The source \ containing the WHL in XML. Cannot be used with `-w`. -* `-t`, `--transmit`** : Transmit the Whiteflag message(s) on the blockchain. Requires `-i`, `-b` and `-a` to be specified. -* `-i`, `--interface`** : The Whiteflag API REST interface \ to post the message(s) to be sent. -* `-b`, `--blockchain`** : The \ to be used for sending the message(s). -* `-a`, `--address`** : The blockchain \ to be used for sending the message(s). +* `-t`, `--transmit` : Transmit the Whiteflag message(s) on the blockchain. Requires `-i`, `-b` and `-a` to be specified. +* `-i`, `--interface` : The Whiteflag API REST interface \ to post the message(s) to be sent. +* `-b`, `--blockchain` : The \ to be used for sending the message(s). +* `-a`, `--address` : The blockchain \ to be used for sending the message(s). * `-o`, `--stdout` : Send the Whiteflag message(s) to stdout. This allows the data to be piped to other processes. * `-v`, `--verbose` : Provide detailed processing output. -**: _in development_ - Other supporting options are: * `--help` : Show help message. @@ -90,7 +88,7 @@ for 3 world heritage sites, with detailed processing information and the Whiteflag messages on standard output: ```shell -wfwhl -s 23 25 32 -f /data/whl.xml -vo +wfwhl -f /data/whl.xml -s 23 25 32 -o -v ``` To send Whiteflag messages for all cultural heritage sites from the WHL XML @@ -100,6 +98,24 @@ list contained in a file to standard output: wfwhl -f /data/whl.xml -o ``` +To transmit Whiteflag messages for 2 specified world heritage sites, with the +Whiteflag API interface and blockchain details in a JSON configuration file +and detailed processing information: + +```shell +wfwhl -s 29 49 --config wfwhl.json -t -v +``` + +where the `wfwhl.json` configuration file contents may look as follows: + +```json +{ + "interface": "http://localhost:5746", + "blockchain": "ethereum", + "address": "10fe33a6a1B26877a2d6fA95eaf4153608B5B5f9" +} +``` + ## License The Whiteflag WHL utility is dedicated to the public domain under the diff --git a/doc/man/wfwhl.1 b/doc/man/wfwhl.1 index 9582ace..96faa8d 100644 --- a/doc/man/wfwhl.1 +++ b/doc/man/wfwhl.1 @@ -13,6 +13,10 @@ Whiteflag is a fully neutral and secure communciations means based on blockchain technology. It enables near real-time communication in armed conflicts and disasters to exchange early warning and status information to create shared situational awareness. +.PP +The Whiteflag messages that are created and sent are: (1) a \fBP52(0)\fR +protective sign, followed by (2) an \fBR1(3)\fR resource message with an URL +linking the protective sign to the corresponding WHL entry. .SH OPTIONS .TP .BR \-s ", " \-\-sites =\fISITEID\fR @@ -27,18 +31,18 @@ The source \fIURL\fR of the WHL in XML on the web. If not specified the default The source \fIFILE\fR containing the WHL in XML. Cannot be used with \fB\-w\fR. .TP .BR \-t ", " \-\-transmit -(NOT IMPLEMENTED) Transmit the Whiteflag message(s) on the blockchain. Requires \fB\-i\fR, +Transmit the Whiteflag message(s) on the blockchain. Requires \fB\-i\fR, \fB\-b\fR and \fB\-a\fR to be specified, either on the command line or using a configuration file with \fB\-\-config\fR. .TP .BR \-i ", " \-\-interface =\fIURL\fR -(NOT IMPLEMENTED) The Whiteflag API REST interface \fIURL\fR to post the message(s) to be sent. +The Whiteflag API REST interface \fIURL\fR to post the message(s) to be sent. .TP .BR \-b ", " \-\-blockchain =\fIBLOCKCHAIN\fR -(NOT IMPLEMENTED) The \fIBLOCKCHAIN\fR to be used for sending the message(s). +The \fIBLOCKCHAIN\fR to be used for sending the message(s). .TP .BR \-a ", " \-\-address =\fIADDRESS\fR -(NOT IMPLEMENTED) The blockchain \fIADDRESS\fR to be used for sending the message(s). +The blockchain \fIADDRESS\fR to be used for sending the message(s). .TP .BR \-o ", " \-\-stdout Send the Whiteflag message(s) to stdout. This allows the data to be piped to other processes. @@ -54,7 +58,7 @@ Show version number. .TP .BR \-\-config =\fIFILE\fR Path to a JSON config \fIFILE\fR with preconfigured arguments; especially useful to -specify Whiteflag API interface URL, blockchain and address. +specify the Whiteflag API interface URL, blockchain and address. .SH LEGAL THE USAGE OF SIGNS AND SIGNALS WITH THIS SOFTWARE IS SUBJECT TO LOCAL AND/OR INTERNATIONAL LAWS .PP diff --git a/lib/arguments.js b/lib/arguments.js deleted file mode 100644 index 52b047f..0000000 --- a/lib/arguments.js +++ /dev/null @@ -1,81 +0,0 @@ -'use strict'; -/** - * @module lib/arguments - * @summary Whiteflag WHL arguments module - * @description Module that handles the command line arguments - */ -module.exports = { - // argument functions - parse: parseArguments -}; - -// Configure option parser // -const args = require('yargs') - .usage('Usage: $0 [-s ...] [-w |-f ]\n [-t -i -b -a
] [-ov]') - .config() - .option('s', { - alias: 'sites', - describe: 'Specify the world heritage site(s) by number', - type: 'array' - }) - .option('w', { - alias: 'web', - describe: 'The of the WHL in XML on the web', - type: 'string', - requiresArg: true, - conflicts: 'f' - }) - .option('f', { - alias: 'file', - describe: 'The containing the WHL in XML', - type: 'string', - requiresArg: true, - normalize: true, - conflicts: 'w' - }) - .option('t', { - alias: 'transmit', - describe: 'Transmit the Whiteflag message(s)', - type: 'boolean', - implies: ['i', 'b', 'a'] - }) - .option('i', { - alias: 'interface', - describe: 'The Whiteflag API REST interface ', - type: 'string', - requiresArg: true - }) - .option('b', { - alias: 'blockchain', - describe: 'The to be used', - type: 'string', - requiresArg: true - }) - .option('a', { - alias: 'address', - describe: 'The blockchain
to be used', - type: 'string', - requiresArg: true - }) - .option('o', { - alias: 'stdout', - describe: 'Send the Whiteflag message(s) to stdout', - type: 'boolean' - }) - .option('v', { - alias: 'verbose', - describe: 'Provide detailed processing output', - type: 'boolean' - }); - -// MAIN MODULE FUNCTIONS // -/** - * Parses the provided command line arguments - * @function parseArguments - * @alias module:lib/arguments.parse - * @param {array} argv array with arguments passed to process - * @param {function} callback function to be called upon completion - */ -function parseArguments(argv, callback) { - return callback(null, args.parse(argv)); -} diff --git a/lib/common/httpreq.js b/lib/common/httpreq.js new file mode 100644 index 0000000..b386316 --- /dev/null +++ b/lib/common/httpreq.js @@ -0,0 +1,110 @@ +'use strict'; +/** + * @module lib/common/httpreq + * @summary Whiteflag WHL common http requests module + * @description Module that handles http requests + */ +module.exports = { + // http functions + get: httpGET, + post: httpPOST +}; + +// Node.js core and external modules // +const http = require('http'); +const https = require('https'); + +/** + * Performs an HTTP GET request + * @function httpGET + * @alias module:lib/common/httpreq.get + * @param {URL} url the URL of the request + * @param {function} callback function to be called upon completion + */ +function httpGET(url, callback) { + const options = { + method: 'GET' + }; + httpRequest(url, options, null, function httpGetCb(err, statusCode, data = null) { + if (!err && statusCode !== 200) { + err = new Error(`Request failed (status code ${statusCode})`); + } + return callback(err, data); + }); +} + +/** + * Performs an HTTP GET request + * @function httpPOST + * @alias module:lib/common/httpreq.post + * @param {URL} url the URL of the request + * @param {data} data the data to be in the request body + * @param {function} callback function to be called upon completion + */ +function httpPOST(url, data, callback) { + const body = JSON.stringify(data); + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }; + httpRequest(url, options, body, function httpPostCb(err, statusCode, data = null) { + if (!err) { + if (statusCode < 200 || statusCode > 202) { + err = new Error(`Request failed (status code ${statusCode})`); + } + } + return callback(err, data); + }); +} + +// PRIVATE FUNCTIONS // +/** + * Performs an HTTP request + * @private + * @param {URL} url the URL of the request + * @param {object} data the data to be in the request body + * @param {function} callback function to be called upon completion + */ +function httpRequest(url, options, body, callback) { + // Create request with protocol specified in url + let req; + const protocol = url.protocol.slice(0, -1); + switch (protocol) { + case 'http': { + req = http.request(url, options, resCb); + break; + } + case 'https': { + req = https.request(url, options, resCb); + break; + } + default: { + // Method does not exist + return callback(new Error(`Unsupported protocol for request: ${protocol}`)); + } + } + // Handle reqest errors + req.on('error', function httpErrCb(err) { + return callback(err); + }); + req.on('timeout', function httpTimeoutCb(err) { + req.abort(); + return callback(new Error(`Aborted request after timeout: ${err.message}`)); + }); + // Send request data + if (body) req.write(body); + req.end(); + + // Callback functions + function resCb(res) { + let data = ''; + res.on('data', function(chunk) { + data += chunk; + }); + res.on('end', function httpProcessCb() { + return callback(null, res.statusCode, data); + }); + } +} diff --git a/lib/httpreq.js b/lib/httpreq.js deleted file mode 100644 index e883f57..0000000 --- a/lib/httpreq.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; -/** - * @module lib/httpreq - * @summary Whiteflag WHL http requests module - * @description Module that handles http requests - */ -module.exports = { - // http functions - get: httpGET -}; - -// Node.js core and external modules // -const https = require('https'); - -/** - * Performs an HTTP GET request - * @function get - * @param {URL} url the URL of the request - * @param {function} callback function to be called upon completion - */ -function httpGET(url, callback) { - https.get(url, function(res) { - let data = ''; - res.on('data', function(chunk) { - data += chunk; - }); - res.on('error', function httpErrCb(err) { - return callback(err); - }); - res.on('timeout', function httpTimeoutCb(err) { - return callback(err); - }); - res.on('end', function httpProcessCb() { - return callback(null, data); - }); - }); -} diff --git a/lib/whiteflag.js b/lib/whiteflag.js index 5639735..ba9341d 100644 --- a/lib/whiteflag.js +++ b/lib/whiteflag.js @@ -6,48 +6,151 @@ */ module.exports = { // Whiteflag functions - processData: processData + createMessages, + sendMessages }; +// WHiteflag WHL modules // +const httpreq = require('./common/httpreq'); + // Module constants // +const WFAPIURL = 'http://localhost:5746'; +const WFAPIENDPOINT = '/messages/send'; +const WFRESOURCE = 'R'; +const WFRESOURCEREFCODE = '3'; const WFPROTECTIVESIGN = 'P'; const WFCULTURALPROPERTY = '52'; -const WFRESOURCE = 'R'; /** - * Processes site data to create and send Whiteflag messages - * @function processData - * @param {array} sites sites to be processed + * Creates Whiteflag messages from WHL site data + * @function createMessages + * @alias module:lib/whiteflag.createMessages + * @param {array} sites the WHL sites to be processed + * @param {object} options the options provided on the command line * @param {function} callback */ -function processData(sites, options, callback) { +function createMessages(sites, options, callback) { + let counter = 0; let wfMessages = []; for (let i = 0; i < sites.length; i++) { + // Create a protective sign and a resource message let wfMessageSet = []; - - // Create a protective sign and send to stdout if option specified wfMessageSet[0] = createMessage(sites[i], WFPROTECTIVESIGN); - if (options.verbose) console.log(`Created a ${messageType(wfMessageSet[0])} message for site ${sites[i].id}`); - if (options.stdout) { - process.stdout.write(JSON.stringify(wfMessageSet[0])); - process.stdout.write('\n'); - } - // Create a resource message and send to stdout if option specified wfMessageSet[1] = createMessage(sites[i], WFRESOURCE); - if (options.verbose) console.log(`Created a ${messageType(wfMessageSet[1])} message for site ${sites[i].id}`); - if (options.stdout) { - process.stdout.write(JSON.stringify(wfMessageSet[1])); - process.stdout.write('\n'); + + // Process message iaw specified options + for (let m = 0; m < wfMessageSet.length; m++) { + counter++; + if (options.blockchain) wfMessageSet[m].MetaHeader.blockchain = options.blockchain; + if (options.address) wfMessageSet[m].MetaHeader.originatorAddress = options.address; + if (options.verbose) console.log(`Created message ${counter}/${(sites.length * 2)}: ${messageType(wfMessageSet[m])} for site ${sites[i].id}`); + if (options.stdout) { + process.stdout.write(JSON.stringify(wfMessageSet[m])); + process.stdout.write('\n'); + } } + // Add messages to message set wfMessages[i] = wfMessageSet; } // All done return callback(null, wfMessages); } +/** + * Sends Whiteflag messages to specified Whiteflag API + * @function sendMessages + * @alias module:lib/whiteflag.sendMessages + * @param {array} wfMessages Whiteflag messages to be sent + * @param {object} options the options provided on the command line + * @param {function} callback + */ +function sendMessages(wfMessages, options, callback) { + if (!options.transmit) return callback(null); + + // Iterate over all messages + let skipped = []; + iterateMessages(); + + /** + /* Iterates over all messages + * @private + */ + function iterateMessages(i = 0) { + // Return if completed + if (i >= wfMessages.length) { + if (skipped.length > 0) { + return callback(new Error(`Could not sent some or all messages for ${skipped.length} sites: ${JSON.stringify(skipped)}`)); + } + return callback(null); + } + // Count messages and get next one to send + let j = (i * 2) + 1; + let wfMessageSet = wfMessages[i]; + + // Send protective sign first + if (options.verbose) console.log(`Sending message ${j}/${(wfMessages.length * 2)}: ${messageType(wfMessageSet[0])} for site ${wfMessageSet[0].MetaHeader.whlSiteNumber}`); + sendMessage(wfMessageSet[0], options, function sendPMessageCb(err, result) { + if (err) { + // Error; skip the related resource message + console.error(`${err.message}`); + console.warn(`Skipping message ${(j + 1)}/${(wfMessages.length * 2)}: ${messageType(wfMessageSet[1])} for site ${wfMessageSet[1].MetaHeader.whlSiteNumber}`); + skipped.push(wfMessageSet[0].MetaHeader.whlSiteNumber); + return iterateMessages(++i, skipped, callback); + } else { + // Send resource message refering to protective sign + wfMessageSet[1].MessageHeader.ReferencedMessage = result.data.MetaHeader.transactionHash; + if (options.verbose) console.log(`Sending message ${(j + 1)}/${(wfMessages.length * 2)}: ${messageType(wfMessageSet[1])} for site ${wfMessageSet[1].MetaHeader.whlSiteNumber}`); + sendMessage(wfMessageSet[1], options, function sendRMessageCb(err) { + if (err) { + console.error(err.message); + skipped.push(wfMessageSet[1].MetaHeader.whlSiteNumber); + } + return iterateMessages(++i, skipped, callback); + }); + } + }); + } +} + +/** + * Sends a Whiteflag message + * @private + * @param {object} wfMessage Whiteflag message to be sent + * @returns {string} Whiteflag message type + */ +function sendMessage(wfMessage, options, callback) { + // Determine Whiteflag API URL to send Whiteflag messages + let url; + if (!options.interface) options.interface = WFAPIURL; + try { + url = new URL(options.interface + WFAPIENDPOINT); // eslint-disable-line no-undef + } catch(err) { + return callback(err); + } + // Send Whiteflag message + httpreq.post(url, wfMessage, function sendMessageCb(err, data) { + if (err && !data) return callback(err); + + // Parse the returned data + let result; + try { + result = JSON.parse(data); + } catch(err) { + return callback(err); + } + // Return result + if (err) return callback(new Error(`${err.message}: ${JSON.stringify(result.errors)}`)); + return callback(null, result); + }); +} + +// PRIVATE FUNCTIONS // /** * Creates a Whiteflag message - * @function createMessage + * @private + * @param {object} site WHL site data + * @param {string} type Whiteflag message code + * @returns {string} Whiteflag message type */ function createMessage(site, type) { const WFMESSAGE = { @@ -75,6 +178,10 @@ function createMessage(site, type) { }; let wfMessage = {}; + // Create message metaheader + wfMessage.MetaHeader = WFMESSAGE.MetaHeader; + wfMessage.MetaHeader.whlSiteNumber = site.id; + // Create message header wfMessage.MessageHeader = WFMESSAGE.MessageHeader; wfMessage.MessageHeader.MessageCode = type; @@ -92,7 +199,7 @@ function createMessage(site, type) { } case WFRESOURCE: { // Message Header - wfMessage.MessageHeader.ReferenceIndicator = '5'; + wfMessage.MessageHeader.ReferenceIndicator = WFRESOURCEREFCODE; wfMessage.MessageHeader.ReferencedMessage = ''; // Message Body @@ -106,11 +213,10 @@ function createMessage(site, type) { return wfMessage; } -// PRIVATE FUNCTIONS // /** * Determines type of message * @private - * @param {object} wfMessage Whiteflag message + * @param {object} wfMessage a Whiteflag message * @returns {string} message type */ function messageType(wfMessage) { @@ -137,7 +243,7 @@ function messageType(wfMessage) { * Create Whiteflag message datetime string * @private * @param {Date} date - * @returns {string} Whiteflag datatime + * @returns {string} Whiteflag datetime */ function wfDateTime(date) { let wfDate = date; diff --git a/lib/sites.js b/lib/whl.js similarity index 84% rename from lib/sites.js rename to lib/whl.js index f8c2d8a..8f216e4 100644 --- a/lib/sites.js +++ b/lib/whl.js @@ -1,12 +1,12 @@ 'use strict'; /** - * @module lib/arguments + * @module lib/whl * @summary Whiteflag WHL arguments module * @description Module that handles the command line arguments */ module.exports = { // WHL site functions - get: getSites + getSites }; // Node.js core and external modules // @@ -14,7 +14,7 @@ const fs = require('fs'); const parseXML = require('xml2js').parseString; // WHiteflag WHL modules // -const httpreq = require('./httpreq'); +const httpreq = require('./common/httpreq'); // Module constants // const WHLNATURAL = 'natural'; @@ -25,8 +25,8 @@ const whlPropertiesRemove = ['query', 'row']; /** * Gets the site information from the WHL * @function getSites - * @alias module:lib/sites.get - * @param {object} options the options for the request + * @alias module:lib/whl.getSites + * @param {object} options the options provided on the command line * @param {function} callback function to be called upon completion */ function getSites(options, callback) { @@ -76,40 +76,40 @@ function getSites(options, callback) { // PRIVATE FUNCTIONS // /** - * Gets the WHL XML data from URL or file and converts it to native object + * Gets the WHL XML data from URL or file and converts it to an object * @private - * @param {URL} url the URL of the WHL list in XML + * @param {object} options the options provided on the command line * @param {function} callback function to be called upon completion */ function getWHL(options, callback) { if (options.file) { // Get WHL XML data from file if (options.verbose) console.log(`Reading WHL from ${options.file}`); - fs.readFile(options.file, function fileGetWHLCb(err, xml) { + fs.readFile(options.file, function fileGetWHLCb(err, data) { if (err) return callback(new Error(`Error while reading WHL from file: ${err.message}`)); // Parse the WHL XML data - parseXML(xml, {explicitArray: false}, function parseXMLCb(err, whl) { + parseXML(data, {explicitArray: false}, function parseXMLCb(err, whl) { if (err) return callback(new Error(`Cannot process XML data from ${options.file}: ${err.message}`)); return callback(null, extractWHL(whl)); }); }); } else { - // Get WHL XML data from an internet resource - if (!options.web) options.web = WHLURL; + // Determine URL to get WHL XML data from an internet resource let url; + if (!options.web) options.web = WHLURL; try { - url = new URL(options.web); + url = new URL(options.web); // eslint-disable-line no-undef } catch(err) { return callback(err); } // Perform HTTP request if (options.verbose) console.log(`Retrieving WHL from ${options.web}`); - httpreq.get(url, function httpGetWHLCb(err, xml) { + httpreq.get(url, function httpGetCb(err, data) { if (err) return callback(new Error(`Error while retrieving WHL from ${options.web}: ${err.message}`)); // Parse the WHL XML data and return resulting list - parseXML(xml, {explicitArray: false}, function parseXMLCb(err, whl) { + parseXML(data, {explicitArray: false}, function parseXMLCb(err, whl) { if (err) return callback(new Error(`Cannot process XML data from ${options.web}: ${err.message}`)); return callback(null, extractWHL(whl)); }); @@ -136,11 +136,11 @@ function extractWHL(whl) { * Gets the site data from WHL data * @private * @param {array} whl the WHL - * @param {number} id the WHL site index number + * @param {number} index the WHL site index number * @returns {object} site data */ function extractSite(whl = [], index = 0) { - // Get site data from WHL entryll + // Get site data from WHL entry const entry = whl[index]; const site = { id: entry.id_number, diff --git a/main.js b/main.js index 0cebfbc..be116df 100755 --- a/main.js +++ b/main.js @@ -1,14 +1,16 @@ #!/usr/bin/env node 'use strict'; /** - * @module index + * @module main * @summary Whiteflag WHL main module * @description Module called first when invoking the Whiteflag WHL utility */ +// Node.js core and external modules // +const yargs = require('yargs'); + // Whiteflag WHL modules // -const args = require('./lib/arguments'); -const sites = require('./lib/sites'); +const whl = require('./lib/whl'); const whiteflag = require('./lib/whiteflag'); /* @@ -32,17 +34,21 @@ main(function mainCb(err, exitcode = 0) { * @param {function} callback */ function main(callback) { - args.parse(process.argv, function argumentsCb(err, options) { - if (err) return callback(err); + // Parse command line options + const options = parseArguments(process.argv); + + // Get the requested WHL site data + whl.getSites(options, function whlGetSitesCb(err, sites) { + if (err) return callback(err, 2); + if (sites.length === 0) return callback(null, 1); - // Get the requested site - sites.get(options, function sitesCb(err, sites) { - if (err) return callback(err, 2); - if (sites.length === 0) return callback(null, 1); + // Create Whiteflag messages from WHL site data + whiteflag.createMessages(sites, options, function wfCreateMessagesCb(err, wfMessages) { + if (err) return callback(err); - // Process Whiteflag messages - whiteflag.processData(sites, options, function wfProcessDataCb(err) { - if (err) return callback(err); + // Send the Whiteflag messages + whiteflag.sendMessages(wfMessages, options, function wfSendMessagesCb(err) { + if (err) return callback(err, 2); return callback(null, 0); }); }); @@ -83,3 +89,71 @@ function uncaughtExceptionCb(err) { } return process.exit(2); } + +/** + * Parses the provided command line arguments + * @private + * @param {array} argv array with arguments passed to process + * @returns {object} parsed options provided on the command line + */ +function parseArguments(argv) { + // Define arguments + const args = yargs + .usage('Usage: $0 [-s ...] [-w |-f ]\n [-t -i -b -a
] [-ov]') + .config() + .option('s', { + alias: 'sites', + describe: 'Specify the world heritage site(s) by number', + type: 'array' + }) + .option('w', { + alias: 'web', + describe: 'The of the WHL in XML on the web', + type: 'string', + requiresArg: true, + conflicts: 'f' + }) + .option('f', { + alias: 'file', + describe: 'The containing the WHL in XML', + type: 'string', + requiresArg: true, + normalize: true, + conflicts: 'w' + }) + .option('t', { + alias: 'transmit', + describe: 'Transmit the Whiteflag message(s)', + type: 'boolean', + implies: ['i', 'b', 'a'] + }) + .option('i', { + alias: 'interface', + describe: 'The Whiteflag API REST interface ', + type: 'string', + requiresArg: true + }) + .option('b', { + alias: 'blockchain', + describe: 'The to be used', + type: 'string', + requiresArg: true + }) + .option('a', { + alias: 'address', + describe: 'The blockchain
to be used', + type: 'string', + requiresArg: true + }) + .option('o', { + alias: 'stdout', + describe: 'Send the Whiteflag message(s) to stdout', + type: 'boolean' + }) + .option('v', { + alias: 'verbose', + describe: 'Provide detailed processing output', + type: 'boolean' + }); + return args.parse(argv); +} diff --git a/package.json b/package.json index c3eab10..e5ddeb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "whiteflag-whl", - "version": "0.1.0", + "version": "0.2.0", "description": "Utility to create and send Whiteflag protective signs for cultural heritage sites listed on the World Heritage List", "keywords": [ "whiteflag",