Skip to content

Commit

Permalink
Improved information reading.
Browse files Browse the repository at this point in the history
  • Loading branch information
serban-petrescu committed Mar 31, 2018
1 parent 652f8b7 commit 9674eff
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 36 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sapim",
"version": "0.0.5",
"version": "0.0.6",
"description": "SAP API Manager Tools",
"main": "dst/index.js",
"files": [
Expand Down
4 changes: 2 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ npm install sapim --save-dev
npm install sapim --save
```
### Binary download
For using the library purely as a command line tool, a binary version (for x64 OS) can be downloaded from the [releases](https://github.com/serban-petrescu/sapim/releases) section. This binary exexcutable does not depend on the presence of NodeJS or NPM on your system.
For using the library purely as a command line tool, a binary version (for x64 OS) can be downloaded from the [releases](https://github.com/serban-petrescu/sapim/releases) section. This binary exexcutable does not depend on the presence of NodeJS or NPM on your system.

## Usage
### Manifests
Expand Down Expand Up @@ -62,7 +62,7 @@ The following commands are available:
- [configure](https://github.com/serban-petrescu/sapim/wiki/Command-Line-Interface#configure)

### Programmatic usage
All the above commands have a corresponding method exposed as part of the library's public API. You can read more about using it [in the corresponding wiki page](https://github.com/serban-petrescu/sapim/wiki/Programmatic-Usage) and you can find the reference documentation [on GitHub Pages](https://serban-petrescu.github.io/sapim/sapim/0.0.2/).
All the above commands have a corresponding method exposed as part of the library's public API. You can read more about using it [in the corresponding wiki page](https://github.com/serban-petrescu/sapim/wiki/Programmatic-Usage) and you can find the reference documentation [on GitHub Pages](https://serban-petrescu.github.io/sapim/sapim/0.0.6/).

Example usage:
```js
Expand Down
9 changes: 9 additions & 0 deletions src/ApiClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import logger from "./logger";
const MAP_CALL_FAILED = "Unable to call key value management endpoint.";
const CSRF_CALL_FAILED = "Unable to retrieve CSRF token.";
const PROXY_CALL_FAILED = "Unable to call API proxy management endpoint.";
const VHOST_CALL_FAILED = "Unable to call virtual host endpoint.";

const MAP_ENTITY_SET_URL = "/Management.svc/KeyMapEntries";
const PROXY_INFO_URL = "/Management.svc/APIProxies";
Expand All @@ -18,6 +19,7 @@ const PROXY_INFO_EXPAND = "$expand=proxyEndPoints,targetEndPoints,apiProducts,pr
"targetEndPoints/conditionalFlows/request/steps,targetEndPoints/conditionalFlows/response/steps," +
"targetEndPoints/properties,proxyEndPoints/properties";
const PROXY_BASE_URL = "/Transport.svc/APIProxies";
const VIRTUAL_HOSTS_URL = "/Management.svc/VirtualHosts";

const CSRF_HEADER = "x-csrf-token";

Expand Down Expand Up @@ -100,4 +102,11 @@ export default class ApiClient {
.then(r => { logger.debug("Successfully read proxy info: " + name + "."); return r.body.d; })
.catch(r => wrapError(r, PROXY_CALL_FAILED));
}

readVirtualHosts() {
return this.client
.then(client => client.get({ uri: VIRTUAL_HOSTS_URL, json: true }))
.then(r => { logger.debug("Successfully read virtual host info."); return r.body.d.results; })
.catch(r => wrapError(r, VHOST_CALL_FAILED));
}
}
43 changes: 42 additions & 1 deletion src/ApiManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import packageManifest, { packageManifestsMatching } from "./command/packageMani
import packageProxy, { packageProxyToFile } from "./command/packageProxy";
import updateMap, { updateMapsFromObject } from "./command/updateMap";
import uploadProxy from "./command/uploadProxy";
import readProxyUrl, { readManifestUrl } from "./command/readProxyUrl";
import { readManifestUrl, readProxyUrl, readVirtualHostById, readDefaultVirtualHost,
readAllVirtualHosts } from "./command/readInfo";

/**
* @typedef {object} Configuration
Expand All @@ -20,6 +21,21 @@ import readProxyUrl, { readManifestUrl } from "./command/readProxyUrl";
* @property {string=} proxy Optional (https) proxy server URI.
*/


/**
* @typedef {object} VirtualHost
* @description An object containing virtual host information
* @property {string} id The id of the virtual host.
* @property {string} name The name of the virtual host.
* @property {string} url The base url for the virtual host.
* @property {string} host The hostname of the virtual host.
* @property {number=} port The port of the virtual host; may be null.
* @property {boolean} ssl Flag indicating if the host is on SSL.
* @property {string=} projectPath The project path on the host; may be null.
* @property {boolean} default Flag indicating if the virtual host is the default one.
*/


/**
* Public API class for the library.
* @class
Expand Down Expand Up @@ -142,6 +158,31 @@ class ApiManager {
return readManifestUrl(this.client, path);
}

/**
* Reads the information for a virtual host (given by id).
* @param {string} id The id of the host.
* @returns {Promise<VirtualHost>} A promise which resolves with the virtual host information.
*/
getVirtualHostInfoById(id) {
return readVirtualHostById(this.client, id);
}

/**
* Reads the information for the default virtual hosts.
* @returns {Promise<VirtualHost>} A promise which resolves with the virtual host information.
*/
getDefaultVirtualHostInfo() {
return readDefaultVirtualHost(this.client);
}

/**
* Reads the information for the all virtual hosts.
* @returns {Promise<VirtualHost[]>} A promise which resolves with the virtual host information.
*/
getAllVirtualHostInfo() {
return readAllVirtualHosts(this.client);
}

/**
* Packages an API proxy described by the given manifest into an archive.
* @param {string} manifestPath The path to the manifest describing the API proxy.
Expand Down
26 changes: 21 additions & 5 deletions src/cli.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#!/usr/bin/env node

import sapim, {createConfigFile} from "./index";
import sapim, { createConfigFile } from "./index";
import program from "commander";
import prompt from "prompt";
import {version, name, description} from "../package.json";
import { version, name, description } from "../package.json";

import logger, {LOG_LEVEL} from "./logger";
import logger, { LOG_LEVEL } from "./logger";

function wrapAction(cb) {
return function(...args) {
return function (...args) {
if (program.silent) {
logger.level = LOG_LEVEL.SILENT;
} else if (program.debug) {
Expand Down Expand Up @@ -88,6 +88,22 @@ program.command("get-manifest-url <path>")
.description("retrieves the base URL for the proxy described by the given manifest")
.action(wrapAction(path => sapim().getManifestUrl(path).then(s => console.log(s))));

program.command("get-vhost-info")
.description("retrieves the information pertaining virtual host(s); without any options, retrieves the default vhost")
.option("-i, --id <id>", "uses the given id to select the vhost")
.option("-a, --all", "retrieves all the virtual host available")
.action(wrapAction(command => {
let result;
if (command.id) {
result = sapim().getVirtualHostInfoById(command.id);
} else if (command.all) {
result = sapim().getAllVirtualHostInfo();
} else {
result = sapim().getDefaultVirtualHostInfo();
}
return result.then(info => console.log(JSON.stringify(info, null, 4)));
}));

program.command("package <manifest> [target_archive]")
.description("package the API proxy described by the given manifest into an archive")
.action(wrapAction((path, target) => sapim().packageManifest(path, target)));
Expand All @@ -112,7 +128,7 @@ program.command("config")
.option("-g, --global", "creates the file globally (in the home dir)")
.option("-f, --force", "overwrites any existing configuration")
.action(wrapAction(options => {
prompt.start({message: ""});
prompt.start({ message: "" });
return new Promise((resolve, reject) => {
prompt.get({
properties: {
Expand Down
95 changes: 95 additions & 0 deletions src/command/readInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import logger from "../logger";
import { parseManifest } from "../utils";

function findDefault(array) {
if (array) {
for (let i = 0; i < array.length; ++i) {
if (array[i].isDefault) {
return array[i];
}
}
}
logger.error("Unable to parse API Management OData response; could not find default object.");
throw new Error("Unable to parse API Management OData response.");
}

function findById(array, id) {
if (array) {
for (let i = 0; i < array.length; ++i) {
if (array[i].id === id) {
return array[i];
}
}
}
logger.error("Unable to parse API Management OData response; could not find object with id: " + id + ".");
throw new Error("Unable to parse API Management OData response.");
}

function nonStartingSlash(uri) {
return uri.indexOf("/") === 0 ? uri.substr(1) : uri;
}

function vhostToUrl(vhost) {
let result = (vhost.isSSL ? "https://" : "http://") + vhost.virtual_host;
if (vhost.virtual_port) {
result += ":" + vhost.virtual_port;
}
result += "/";
if (vhost.projectPath) {
result += nonStartingSlash(vhost.projectPath) + "/";
}
return result;
}

function parseVirtualHost(vhost) {
return {
url: vhostToUrl(vhost),
ssl: vhost.isSSL || false,
id: vhost.id,
name: vhost.name,
default: vhost.isDefault,
host: vhost.virtual_host,
port: vhost.virtual_port || null,
projectPath: vhost.projectPath || null
};
}

export function readAllVirtualHosts(client) {
return client.readVirtualHosts().then(info => {
logger.debug("Got vhost information and retrieved all vhosts.");
let result = [];
for (let vhost of info) {
result.push(parseVirtualHost(vhost));
}
return result;
});
}

export function readVirtualHostById(client, id) {
return client.readVirtualHosts().then(info => {
let vhost = findById(info, id);
logger.debug("Got vhost information and retrieved vhost with id: " + id + ".");
return parseVirtualHost(vhost);
});
}

export function readDefaultVirtualHost(client, id) {
return client.readVirtualHosts().then(info => {
let vhost = findDefault(info, id);
logger.debug("Got vhost information for default vhost.");
return parseVirtualHost(vhost);
});
}

export function readProxyUrl(client, name) {
return client.readProxyInfo(name).then(info => {
logger.debug("Got information for proxy:" + name + ".");
let proxy = findDefault(info.proxyEndPoints.results);
let host = findDefault(proxy.virtualhosts.results);
return vhostToUrl(host) + nonStartingSlash(proxy.base_path);
});
}

export function readManifestUrl(client, path) {
return parseManifest(path).then(manifest => readProxyUrl(client, manifest.proxy.name));
}
27 changes: 0 additions & 27 deletions src/command/readProxyUrl.js

This file was deleted.

0 comments on commit 9674eff

Please sign in to comment.