liveapicreator-admin-cli
Version:
The NodeJS command line utility for 'CA Live API Creator' DevOps Administration from CA Technologies
98 lines • 38.3 kB
JSON
{
"{d}test": {
"{f}exportoptions.json": {
"passwordStyle": "SKIP",
"apiOptionStyle": "EMIT_ALL",
"authTokenStyle": "SKIP_AUTO",
"skipUrlFragmentWrapping": false,
"libraryStyle": "EMIT_ALL",
"schemaCacheStyle": "DO_NOT_EMIT",
"filters": {
"key": [
"libraries"
]
}
},
"{d}libraries": {
"{f}ReadMe.md": "This folder contains definitions for libraries and whether they are used.\n",
"{f}SystemLibraryUsage.json": [],
"{f}AdmAuth-1.0.json": {
"name": "AdmAuth",
"version": "1.0",
"isUsedByProject": false,
"title": "AdminAuthProvider",
"description": "AuthProvider for Developer Access (not used, example only)",
"groupName": "newlib",
"docsURL": "",
"referenceURL": ""
},
"{f}AdmAuth-1.0.js": "// Custom authentication provider, for admin user authentication (access to API Creator).\n// Authenticates hard coded users; in real-life, you might authenticate against LDAP, AD, etc.\n\n// At its core, an Authorization Provider is a JavaScript (create) function\n// that returns an object (see end) containing these 4 functions:\n// configure: function(values) {...},\n// authenticate(payload) {...},\n// getConfigInfo: function() {...},\n// getLoginInfo: function() {...}\n\n\nout = java.lang.System.out;\n\n// register this create function to LAC.\n// as above, it returns an object containing the 4 functions noted above.\nfunction create() {\n\n var result = {}; // returned to LAC, containing the 4 functions noted above\n var configSetup = {\n keyLifetimeMinutes : 60\n };\n var allRoles = ['System administrator', 'Account admin', 'Data admin', 'Data designer'];\n\n\n // This function is called by API Creator when the user enters a value\n // for the parameters specified by getConfigInfo and clicks Save.\n // Returns configuration values which API Creator will save into Admin DB;\n // these are exported in the json config file\n result.configure = function configure(myConfig) {\n configSetup.keyLifetimeMinutes = myConfig.keyLifetimeMinutes || 60;\n };\n\n\n // Main crux of Auth Provider - called by API Server on post to @authenticate, to return list of Roles\n // NOTE: the function configure must be called first - this will validate the user/pw\n\n // Eg, you might with to query LDAP, Active Directory etc, to empower corporate users\n // to use Live API Creator to create database.\n // You will also need to compute the proper admin roles explained in the product documentation\n // under Admin Authentication Providers\n\n // The argument passed in will contain whatever values were provided to the @authentication service.\n // If the caller is well-behaved, this should correspond to the parameters described by getLoginInfo,\n // but you should not depend on that.\n\n // This function must return an object containing just an error message if the authentication failed.\n // If the authentication succeeded, then it must return an object with the following properties:\n result.authenticate = function authenticate(payload) {\n\n out.println(\"Admin Authentication called...\");\n\n var roles = [];\n var errorMsg = \"Sorry, you are not authorized\";\n var resetPasswordURL = null;\n var forgotPasswordURL = null;\n var myUserData = [];\n var autResponse = errorMsg;\n\n // these hard-coded users are in lieu of actually doing a query against LDAP, AD etc.\n if (payload.username == 'admin' || payload.username == 'demo' || payload.username == 'sa' || payload.username == 'boris') {\n out.println(\"Admin Authentication - default admin/demo/sa user - good to go..\");\n roles = allRoles; // || HARD CODED FOR DEMO (we even ignore the pwd)\n myUserData = {accountIdent:'1000'};\n if (payload.username == 'demo') {\n myUserData = {accountIdent:'1'};\n out.println(\"... with SA account visibility..\");\n }\n autResponse = {\n errorMessage : null,\n roleNames : roles,\n userIdentifier : payload.username,\n keyExpiration : new Date(+new Date()\n + (+configSetup.keyLifetimeMinutes) * 60 * 1000),\n userData : myUserData,\n userInfo : myUserData,\n lastLogin : {\n datetime : null,\n ipAddress : null\n }\n };\n out.println(\"Admin Authentication successful - returning..\" + JSON.stringify(autResponse));\n return autResponse;\n } else {\n out.println(\"Admin Authentication FAILED!\");\n return {\n errorMessage : errorMsg,\n roleNames : roles,\n userIdentifier : payload.username,\n keyExpiration : new Date(+new Date()\n + (+configSetup.keyLifetimeMinutes) * 60 * 1000),\n userData : myUserData,\n userInfo : myUserData,\n lastLogin : {\n datetime : null,\n ipAddress : null\n }\n };\n }\n };\n\n\n // FUNCTION getLoginInfo is used to create the login dialog - DO NOT CHANGE\n // This function is called by API Server when a client needs to know what kind of information is required for authentication.\n // Basically, this describes what the login dialog should look like (assuming the client is an interactive application).\n result.getLoginInfo = function getLoginInfo() {\n return {\n fields : [\n {\n name : \"username\",\n display : \"Username\",\n description : \"Enter your First Name\",\n type : \"text\",\n length : 40,\n helpURL : \"http://liveapicreator.ca.com\"\n },\n {\n name : \"password\",\n display : \"Password\",\n description : \"Enter your Last Name as Password\",\n type : \"password\",\n length : 40,\n helpURL : \"http://liveapicreator.ca.com/\"\n } ],\n links : [\n ]\n };\n };\n\n result.getConfigInfo = function getConfigInfo() {\n return {\n current : {\n \"keyLifetimeMinutes\" : configSetup.keyLifetimeMinutes\n },\n fields : [\n {\n name : \"keyLifetimeMinutes\",\n display : \"API Key Lifetime (Minutes)\",\n type : \"number\",\n length : 8,\n helpURL : \"http://www.liveapicreator.ca.com\"\n } ],\n links : []\n };\n }\n\n // returns object containing the 4 functions that define a Custom Authentication Provider:\n // getConfigInfo: function() {...}, configure: function(values) {...}, getLoginInfo: function() {...}, authenticate:\n\n // returns the 4 functions\n return result;\n}\n",
"{f}b2bB2B-1.0.json": {
"name": "b2bB2B",
"version": "1.0",
"isUsedByProject": false,
"title": "B2BLib",
"description": "Various B2B services (invoked from JavaScript Logic)",
"groupName": "newlib",
"docsURL": "",
"referenceURL": ""
},
"{f}b2bB2B-1.0.js": "var B2B = {}; // a common JavaScript technique to name-scope shared functions\n//TODO: employ arrow functions when fully supported by Nashorn\n\nB2B.transformToWebHook = function transformToWebHook(aLogicContext, aResourceName, aTargetUrl) {\n aLogicContext.logDebug(\"*** B2B.transformToWebHook *** using: \" + aResourceName + \", to: \" + aTargetUrl);\n var resourceURL = aTargetUrl; // \"http://localhost:8080/rest/default/b2bderbypavlov/v1/SalesReports\";\n\n // custom resource provides name mapping\n // readiness lab: uncomment this =====>\n // aLogicContext.logDebug(\"getting aLogicContext.getTableDefinition()\");\n var metaTable = aLogicContext.getTableDefinition();\n aLogicContext.logDebug(\"*** transformToWebHook *** metaTable: \" + metaTable);\n var options = {sysfilter: \"equal(OrderID:\" + aLogicContext.getCurrentState().OrderID + \")\"\n ,\"sysfilter..SupplierAlert.Order_DetailsList.Product.Supplier\": \"equal(CompanyName: '\" + \"Pavlova, Ltd.\" + \"')\" };\n var resourceGetResponse = SysUtility.getResource(aResourceName, options); // FIXME\n\n // system console output\n aLogicContext.logDebug(\"B2B.transformToWebHook posting getResponse: \" + JSON.stringify(resourceGetResponse).substring(1, 20) + \"...\");\n aLogicContext.logDebug(\"B2B.transformToWebHook to URL: \" + resourceURL);\n\n if (resourceURL === null || resourceURL === \"\") {\n out = java.lang.System.out;\n out.println(\"WebHook URL is null/empty - this not posted:\\n\" + (JSON.stringify(resourceGetResponse)).substring(1, 4) + \"...\");\n }\n else {\n var settings = { headers: { Authorization: \"CALiveAPICreator supplier:1\" }}; // FIXME\n var postResponse = SysUtility.restPost(resourceURL, null, settings, resourceGetResponse);\n\n // API Creator log output\n // log.debug('ok, using re-usable solution');\n if (JSON.parse(postResponse).statusCode !== 201) {\n throw \"B2B.transformToWebHook unexpected post response: \" + postResponse;\n }\n }\n\n return null;\n};\n\n\nB2B.sendToWebHook = function sendToWebHook(aPostRequest, aTargetUrl) {\n resourceURL = aTargetUrl;\n var tryIt = true;\n if (tryIt === true) {\n if (resourceURL === null || resourceURL === \"\") {\n out = java.lang.System.out;\n out.println(\"WebHook URL is null/empty - this not posted:\\n\" + (JSON.stringify(aPostRequest)).substring(1, 20) + \"...\");\n }\n else {\n var settings = { headers: { Authorization: \"CALiveAPICreator supplier:1\" }}; // FIXME\n var postResponse = SysUtility.restPost(resourceURL, null, settings, aPostRequest);\n\n // API Creator log output\n // log.debug('ok, using re-usable solution');\n if (JSON.parse(postResponse).statusCode !== 201) {\n throw \"B2B.sendToWebHook unexpected post response: \" + postResponse;\n }\n }\n }\n return null;\n};\n\n\n// you can save state in logicContext.userProperties, including complex objects such as Maps\n\nB2B.putPropertyMap = function putPropertyMap(logicContext, propertyName, key, value) {\n var RestRequest = Java.type('com.kahuna.server.rest.RestRequest');\n var req = RestRequest.getCurrentRestRequest();\n logicContext.logDebug(\"*** B2B.putPropertyMap - propertyName: \" + propertyName + \", key: \" + key + \", value: \" + value + \", on req: \" + req);\n var property = req.getUserProperties().get(propertyName); // userProperties to maintain state in transaction\n if (property === null) {\n property = new java.util.HashMap();\n }\n property.put(key, value);\n req.setUserProperty(propertyName, property);\n};\n\n\n//approach for global (static) properties (dynamic properties can be saved in req.getUserProperties().get)\n//(alternative: store them in a 1 row table, edit with Data Explorer, accessors here)\n\nB2B.supplierURL = function supplierURL(req) {\n var resultURL = req.localFullBaseURL.replace(\"nw\",\"pavlov\");\n out.println(\"B2B.supplierURL returns: \" + resultURL);\n return resultURL;\n};\n\n\n//returns a sample order, for testing\n\nB2B.sampleOrder = function sampleOrder() {\n var newPartnerOrderJson =\n {\n \"CustomerNumber\": \"VINET\",\n \"Items\": [\n {\n \"Product\": {\n \"ProductName\": \"Pavlova\"\n },\n \"Quantity\": 1\n }, {\n \"Product\": {\n \"ProductName\": \"Uncle Bob's Organic Dried Pears\"\n },\n \"Quantity\": 2\n }, {\n \"Product\": {\n \"ProductName\": \"Tofu\"\n },\n \"Quantity\": 3\n }, {\n \"Product\": {\n \"ProductName\": \"Ikura\"\n },\n \"Quantity\": 4\n }, {\n \"Product\": {\n \"ProductName\": \"Konbu\"\n },\n \"Quantity\": 5\n }, {\n \"Product\": {\n \"ProductName\": \"Alice Mutton\"\n },\n \"Quantity\": 1\n }\n ],\n \"Shipper\": {\n \"CompanyName\": \"Federal Shipping\"\n }\n };\n\n return newPartnerOrderJson;\n};\n\n\n// send email\n\nB2B.sendEmail = function sendEmail() {\n var result = {};\n var msg = \"error\";\n var configSetup = {\n to: \"to\",\n from: \"from\",\n title: \"title\",\n text: \"text\"\n };\n\n result.configure = function configure(myconfig) {\n configSetup.to = myconfig.to || \"to\";\n configSetup.from = myconfig.from || \"from\";\n configSetup.title = myconfig.title || \"title\";\n configSetup.text = myconfig.text || \"text\";\n };\n\n result.send = function send() {\n try {\n // call my mail interface here\n msg = \"Send email (stub) title: \" + configSetup.title + \" to: \" + configSetup.to + \", from: \" + configSetup.from + \" body text: \" + configSetup.text;\n }\n catch (e) {\n return e;\n }\n out.println(\"B2B.sendMail returns: \" + msg);\n return msg;\n };\n\n return result;\n}\n\n\n// minor debug helper, to prevent NPE in logging anObject.toString\n// where anObject is null\n\nB2B.db = function db(anObject) {\n var result = \"null\";\n if (anObject !== null) {\n result = anObject.toString();\n }\n return result;\n};\n\n\n// copies like-named attributes from logicContext's row -> targetRow,\n// ignoring attributes part of pKey\n\nB2B.copyAttributes = function copyAttributes(logicContext, targetRow) {\n\n sourceRow = logicContext.getCurrentState();\n\n var sourceMetaEntity = sourceRow.getMetaEntity();\n var targetMetaEntity = targetRow.getMetaEntity();\n\n logicContext.touch(targetRow);\n var debugMoved = [];\n\n for each (var eachProp in sourceMetaEntity.getProperties()) {\n if ( eachProp.isAttribute() ) {\n var targetMetaProp = targetMetaEntity.getPropertyByName(eachProp.name);\n // NB: cannot use hasOwnProperty (Java obj, not JS)\n if (null !== targetMetaProp) {\n if (targetMetaProp.isInPrimaryKey() === true) {\n // logicContext.logDebug(\"copyAttributes - skipping eachProp since in pKey: \" + eachProp.name);\n }\n else {\n var propValue = sourceRow[eachProp.name];\n targetRow[eachProp.name] = propValue;\n debugMoved.push(eachProp.name);\n }\n }\n else {\n // logicContext.logDebug(\"copyAttributes - skipping eachProp since not in target: \" + eachProp.name);\n }\n }\n }\n logicContext.logDebug(\"copyAttributes - moved: [\" + debugMoved + \"]\");\n logicContext.update(targetRow);\n};\n",
"{f}ConfLib-1.0.json": {
"name": "ConfLib",
"version": "1.0",
"isUsedByProject": false,
"title": "ConfLib",
"description": "Reuse (constant strings, etc)",
"groupName": "newlib",
"docsURL": null,
"referenceURL": null
},
"{f}ConfLib-1.0.js": "var ConfigLib = { // preferably, load values from property files, as in Conference - Management\n confOfferURLFragment: \"conf-offer\",\n confManagementURLFragment: \"conf-management\",\n confManagementURL: 'http://localhost:8080/rest/default/conf-management/v1/ProcessCharges',\n confManagementAuth: { headers: { Authorization: \"CALiveAPICreator AcctgToken:1\" }}, // see Auth Tokens screen\n confOfferAuth: { headers: { Authorization: \"CALiveAPICreator AdminKey:1\" }}\n \n};\n",
"{f}ConfManagementLib-1.0.json": {
"name": "ConfManagementLib",
"version": "1.0",
"isUsedByProject": false,
"title": "ConfManagementLib",
"description": "This is a JavaScript library",
"groupName": "newlib",
"docsURL": null,
"referenceURL": null
},
"{f}ConfManagementLib-1.0.js": "var Config = { // a common technique for name-spacing in JavaScipt\n created: new Date(),\n save: function save(aMkt) {\n Config.settings = aMkt;\n Config.modified = new Date();\n // print(\"ConfManagementLib Config'd: \" + JSON.stringify(Config));\n }\n};\n\nprint(\"\\nConfig loaded: \" + JSON.stringify(Config) + \"\\n\");\n",
"{f}CustomAuth-1.0.json": {
"name": "CustomAuth",
"version": "1.0",
"isUsedByProject": false,
"title": "B2BAuthProvider",
"description": "AuthProvider using REST on Employees Table (requires install)",
"groupName": "newlib",
"docsURL": "",
"referenceURL": ""
},
"{f}CustomAuth-1.0.js": "// Custom authentication provider, uploaded in B2B install script.\n// Authenticates using RESTful service, configured to be employees table in Northwind-B2B.\n\n// At its core, an Authorization Provider is a JavaScript function that returns an object (see end) containing these 4 functions:\n// getConfigInfo: function() {...}, configure: function(values) {...}, getLoginInfo: function() {...}, authenticate:\n//\n\nout = java.lang.System.out;\n\nfunction create() {\n\n var result = {};\n var configSetup = {\n logonApiKey : '',\n loginBaseURL : '',\n loginGroupURL : '',\n keyLifetimeMinutes : 60\n };\n\n\n // This function is called by API Creator when the user enters a value\n // for the parameters specified by getConfigInfo and clicks Save.\n // Returns configuration values which API Creator will save into Admin DB;\n // these are exported in the json config file\n result.configure = function configure(myConfig) {\n configSetup.logonApiKey = myConfig.logonApiKey || 'demo_full'; // supply, or default\n configSetup.loginBaseURL = myConfig.loginBaseURL || 'http://localhost:8080/rest/default/v1/...';\n configSetup.loginGroupURL = myConfig.loginGroupURL || 'http://localhost:8080/rest/default/v1/...';\n configSetup.keyLifetimeMinutes = myConfig.keyLifetimeMinutes || 60;\n };\n\n\n // Main crux of Auth Provider - called by API Server on post to @authenticate, to return list of Roles\n // NOTE: the function configure must be called first - this will validate the user/pw\n\n // The argument passed in will contain whatever values were provided to the @authentication service.\n // If the caller is well-behaved, this should correspond to the parameters described by getLoginInfo,\n // but you should not depend on that.\n\n // This function must return an object containing just an error message if the authentication failed.\n // If the authentication succeeded, then it must return an object with the following properties:\n result.authenticate = function authenticate(payload) {\n\n out.println(\"Authentication called...\");\n\n var roles = [];\n var errorMsg = null;\n var resetPasswordURL = null;\n var forgotPasswordURL = null;\n var myUserData = [];\n var params = null;\n var settings = {\n headers : {\n 'Authorization' : 'CALiveAPICreator ' + configSetup.logonApiKey + ':1'\n }\n };\n\n try {\n if (payload.username == 'admin' || payload.username == 'demo') {\n out.println(\"Authentication - default admin/demo/ user - good to go..\");\n // out.println(\"Lab test OK...\"); // uncomment this for Readiness Lab\n roles = ['Full access']; // || HARD CODED FOR DEMO (we even ignore the pwd)\n errorMsg = null; // authorized successfully\n }\n else if (payload.username == 'pavlov' || payload.username == 'Pavlov') {\n out.println(\"Authentication - Pavlov - role is Supplier, with Global ID===7\");\n roles = ['Supplier']; // Permission's Row Filter uses the following Global\n myUserData = {ID: '7', AnotherParm: 'like this'}; // reference like this: \"SupplierID\" = @{ID}\n errorMsg = null; // authorized successfully\n }\n else {\n // GET this JSON request to determine if username and password is valid\n // if so, return an array of role names (here just 'Full Access')\n // and, to simplify typing in demos, will allow the default Password1\n var pwd = payload.password;\n if (payload.username == \"Janet\" && payload.password == \"Password1\") {\n pwd = \"Leverling\";\n }\n var loginAttemptURL = configSetup.loginBaseURL\n + \"?sysfilter=equal(FirstName:'\"+ payload.username\n + \"')&sysfilter=equal(LastName:'\" + pwd\n + \"')\";\n out.println(\"Authentication - finding [\" + payload.username + \".\" + pwd + \"]\");\n out.println(\"... via Rest URL: \" + loginAttemptURL);\n out.println(\"... using settings: \" + JSON.stringify(settings));\n var loginAttempt = SysUtility.restGet(loginAttemptURL, params, settings);\n var groups = JSON.parse(loginAttempt);\n // out.println(JSON.stringify(groups, null, 2));\n\n if (groups.hasOwnProperty('errorMessage')) {\n out.println(\"...errorMessage found in loginAttempt: \" + loginAttempt);\n errorMsg = groups.errorMessage;\n }\n else {\n // change the field name below .name to the name of your\n // roleName column\n errorMsg = 'Username ' + payload.username + ' not found with last name as password';\n for ( var row in groups) {\n roles = ['Full access']; // || HARD CODED FOR DEMO\n // roles.push(groups[row].Region);\n // myUserData.push(groups[row].Region)\n errorMsg = null; // if one role is found then we are good to return\n }\n }\n if (errorMsg != null) {\n out.println(\"...get failed to find this user, loginAttempt: \" + loginAttempt);\n }\n }\n }\n catch (e) {\n errorMsg = e.message;\n }\n\n var autResponse = {\n errorMessage : errorMsg,\n roleNames : roles,\n userIdentifier : payload.username,\n keyExpiration : new Date(+new Date()\n + (+configSetup.keyLifetimeMinutes) * 60 * 1000),\n userData : myUserData,\n lastLogin : {\n datetime : null,\n ipAddress : null\n }\n };\n return autResponse;\n };\n\n\n // FUNCTION getAllGroups is used to map all available groups for existing application -\n // unused in this example, provided for illustration purposes only...\n result.getAllGroups = function getAllGroups() {\n var roles = [];\n var errorMsg = null;\n var params = null;\n var settings = {\n headers : {\n 'Authorization' : 'CALiveAPICreator ' + configSetup.logonApiKey + ':1'\n }\n };\n\n try {\n var loginAttemptURL = configSetup.loginGroupURL; // no filter needed- get all roles?\n var groupsResponse = SysUtility.restGet(loginAttemptURL, params,\n settings);\n var groups = JSON.parse(groupsResponse);\n if (groups.hasOwnProperty('errorMessage')) {\n errorMsg = groups.errorMessage;\n }\n else {\n // change the .name to refrelect the name of your roles returned\n // in the JSON object\n for ( var row in groups) {\n roles.push(groups[row].name);\n }\n }\n }\n catch (e) {\n errorMsg = e.message;\n }\n\n var autResponse = {\n errorMessage : errorMsg,\n roleNames : roles\n };\n\n return autResponse;\n };\n\n\n // FUNCTION getLoginInfo is used to create the login dialog - DO NOT CHANGE\n // This function is called by API Server when a client needs to know what kind of information is required for authentication.\n // Basically, this describes what the login dialog should look like (assuming the client is an interactive application).\n result.getLoginInfo = function getLoginInfo() {\n return {\n fields : [\n {\n name : \"username\",\n display : \"Username\",\n description : \"Enter your First Name\",\n type : \"text\",\n length : 40,\n helpURL : \"http://liveapicreator.ca.com\"\n },\n {\n name : \"password\",\n display : \"Password\",\n description : \"Enter your Last Name as Password\",\n type : \"password\",\n length : 40,\n helpURL : \"http://liveapicreator.ca.com/\"\n } ],\n links : [\n\n ]\n };\n };\n\n result.getConfigInfo = function getConfigInfo() {\n return {\n current : {\n \"keyLifetimeMinutes\" : configSetup.keyLifetimeMinutes,\n \"logonApiKey\" : configSetup.logonApiKey,\n \"loginBaseURL\" : configSetup.loginBaseURL,\n \"loginGroupURL\" : configSetup.loginGroupURL\n },\n fields : [ {\n name : \"logonApiKey\",\n display : \"logonApiKey\",\n type : \"text\",\n length : 60,\n helpURL : \"\"\n }, {\n name : \"loginBaseURL\",\n display : \"loginBaseURL\",\n type : \"text\",\n length : 120,\n helpURL : \"\"\n }, {\n name : \"loginGroupURL\",\n display : \"loginGroupURL\",\n type : \"text\",\n length : 120,\n helpURL : \"\"\n }, {\n name : \"keyLifetimeMinutes\",\n display : \"API Key Lifetime (Minutes)\",\n type : \"number\",\n length : 8,\n helpURL : \"http://www.liveapicreator.ca.com\"\n } ],\n links : []\n };\n };\n\n // returns object containing the 4 functions that define a Custom Authentication Provider:\n // getConfigInfo: function() {...}, configure: function(values) {...}, getLoginInfo: function() {...}, authenticate:\n\n return result; // returns the 4 func\n}\n",
"{f}insertActions-1.0.json": {
"name": "insertActions",
"version": "1.0",
"isUsedByProject": false,
"title": "InsertActionsLib",
"description": "Inject @metadata Action tags (e.g., Lookup), for Request Events",
"groupName": "newlib",
"docsURL": "",
"referenceURL": ""
},
"{f}insertActions-1.0.js": "var insertActions = {}; // a common JavaScript technique to name-scope shared functions\n\n\n// internal routine to fix path expression from jsonPath (another library)\n\nvar fixPathObject = function fixPathObject(path,jsonObj) {\n var index = path;//'[\\'Items\\'][0][\\'Product\\']';\n var res = index.split(\"]\");\n res.splice(res.length-1,1);\n var target = jsonObj;\n for (var i = 0; i < res.length; i++) {\n var replacement = res[i].replace(\"[\",\"\").replace(\"'\",\"\").replace(\"'\",\"\");\n target = target[replacement];\n }\n return target;\n};\n\n\n// internal routine to create metadata tag\n\nvar getMetadataTag = function getMetadataTag(anAction) {\n var result = null;\n if (anAction === \"LOOKUP\") {\n result = { \"action\": \"LOOKUP\" };\n }\n else if (anAction === \"MERGE_INSERT\") {\n result = { \"action\": \"MERGE_INSERT\" };\n }\n else {\n throw \"insertAction tag must be LOOKUP or MERGE_INSERT\";\n }\n return result;\n};\n\n\n// internal routine to insert the tag (iff it does not already exist)\n\nvar insertActionTag = function insertActionTag(aTarget, aTag) {\n if (typeof aTarget[\"@metadata\"] !== \"undefined\") {\n // log.debug(dbTitle + \" *** metadata tag already exists, no action taken\");\n }\n else {\n aTarget[\"@metadata\"] = getMetadataTag(aTag);\n }\n};\n\nfunction db(aString) {\n log.debug(aString);\n print (aString);\n}\n\n\n/* insert metadata actions tags for resource into json string, (e.g., LOOKUP) iff they don't already exist\n returns json string of altered request\n \n example from B2B: PartnerOrder has res.extendedProperties: {\n \"InsertActions\": [\n {\n \"path\": \"$..Product\",\n \"insertActions\": \"LOOKUP\"\n },\n {\n \"path\": \"Shipper\",\n \"insertActions\": \"LOOKUP\"\n }\n ]\n}\n json = insertActions.insertActions(req, json, actions); // API Server processes this...\n*/\n\ninsertActions.insertActionsForResource = function insertActionsForResource(json, actions) {\n var dbTitle = \"insertActions.InsertActionsForResource: \";\n // db(dbTitle + \"running with actions: \" + JSON.stringify(actions) + \", json -->\\n\" + json);\n if (json === null) {\n return json;\n }\n var jsonObj = null; // hold off on parse, until we are sure this resource is relevant\n\n // for (let eachAction of actions) { -- syntax not supported\n for each (var eachAction in actions) {\n if (jsonObj === null) {\n jsonObj = JSON.parse(json);\n }\n if (eachAction.path === \"\") {\n insertActionTag(jsonObj, eachAction.insertActions); // root\n }\n else {\n var paths = jsonPath(jsonObj, eachAction.path, {resultType:\"PATH\"});\n for each (var eachPath in paths) { // perform insertion for eachPath\n var target = fixPathObject(eachPath.substring(1), jsonObj);\n insertActionTag(target, eachAction.insertActions);\n }\n }\n }\n\n if (jsonObj === null) {\n return json;\n }\n else {\n return JSON.stringify(jsonObj);\n }\n};\n\n\n// insert metadata action tags into json string, (e.g., LOOKUP) iff they don't already exist\n// actions array is {resource-name, path-for-insert, \"INSERT\" || \"MERGE_INSERT\"}\n// returns json string of altered request\n// example from B2B:\n// var actions = [\n// {resource: \"PartnerOrder\", path: \"$..Product\", insertActions: \"LOOKUP\"},\n// {resource: \"PartnerOrder\", path: \"Shipper\", insertActions: \"LOOKUP\"}\n// ];\n// json = insertActions.insertActions(req, json, actions); // API Server processes this...\n\ninsertActions.insertActions = function insertActions(req, json, actions) {\n var dbTitle = \"InsertActions: \";\n if (json === null) {\n db(dbTitle + \"null request object - no action\");\n return json;\n }\n var jsonObj = null; // hold off on parse, until we are sure this resource is relevant\n\n // for (let eachAction of actions) { -- syntax not supported\n for each (var eachAction in actions) {\n if (req.resourceName === eachAction.resource) {\n if (jsonObj === null) {\n jsonObj = JSON.parse(json);\n }\n if (eachAction.path === \"\") {\n insertActionTag(jsonObj, eachAction.insertActions); // root\n }\n else {\n var paths = jsonPath(jsonObj, eachAction.path, {resultType:\"PATH\"});\n log.debug(dbTitle + \"paths: \" + paths); // ==> [ $['Items'][0]['Product'] ...]\n for each (var eachPath in paths) { // perform insertion for eachPath\n var target = fixPathObject(eachPath.substring(1), jsonObj);\n insertActionTag(target, eachAction.insertActions);\n }\n }\n }\n }\n\n if (jsonObj === null) {\n db(dbTitle + \"no change\");\n return json;\n }\n else {\n db(dbTitle + \"transformed to: \" + JSON.stringify(jsonObj));\n return JSON.stringify(jsonObj);\n }\n};\n",
"{f}jsonpath-0.8.0.json": {
"name": "jsonpath",
"version": "0.8.0",
"isUsedByProject": false,
"title": "JsonPathLib",
"description": "Used by InsertActionsLib",
"groupName": "newlib",
"docsURL": "",
"referenceURL": ""
},
"{f}jsonpath-0.8.0.js": "/* JSONPath 0.8.0 - XPath for JSON\n\n *\n\n * Copyright (c) 2007 Stefan Goessner (goessner.net)\n\n * Licensed under the MIT (MIT-LICENSE.txt) licence.\n\n */\n\nfunction jsonPath(obj, expr, arg) {\n\n var P = {\n\n resultType: arg && arg.resultType || \"VALUE\",\n\n result: [],\n\n normalize: function(expr) {\n\n var subx = [];\n\n return expr.replace(/[\\['](\\??\\(.*?\\))[\\]']/g, function($0,$1){return \"[#\"+(subx.push($1)-1)+\"]\";})\n\n .replace(/'?\\.'?|\\['?/g, \";\")\n\n .replace(/;;;|;;/g, \";..;\")\n\n .replace(/;$|'?\\]|'$/g, \"\")\n\n .replace(/#([0-9]+)/g, function($0,$1){return subx[$1];});\n\n },\n\n asPath: function(path) {\n\n var x = path.split(\";\"), p = \"$\";\n\n for (var i=1,n=x.length; i<n; i++)\n\n p += /^[0-9*]+$/.test(x[i]) ? (\"[\"+x[i]+\"]\") : (\"['\"+x[i]+\"']\");\n\n return p;\n\n },\n\n store: function(p, v) {\n\n if (p) P.result[P.result.length] = P.resultType == \"PATH\" ? P.asPath(p) : v;\n\n return !!p;\n\n },\n\n trace: function(expr, val, path) {\n\n if (expr) {\n\n var x = expr.split(\";\"), loc = x.shift();\n\n x = x.join(\";\");\n\n if (val && val.hasOwnProperty(loc))\n\n P.trace(x, val[loc], path + \";\" + loc);\n\n else if (loc === \"*\")\n\n P.walk(loc, x, val, path, function(m,l,x,v,p) { P.trace(m+\";\"+x,v,p); });\n\n else if (loc === \"..\") {\n\n P.trace(x, val, path);\n\n P.walk(loc, x, val, path, function(m,l,x,v,p) { typeof v[m] === \"object\" && P.trace(\"..;\"+x,v[m],p+\";\"+m); });\n\n }\n\n else if (/,/.test(loc)) { // [name1,name2,...]\n\n for (var s=loc.split(/'?,'?/),i=0,n=s.length; i<n; i++)\n\n P.trace(s[i]+\";\"+x, val, path);\n\n }\n\n else if (/^\\(.*?\\)$/.test(loc)) // [(expr)]\n\n P.trace(P.eval(loc, val, path.substr(path.lastIndexOf(\";\")+1))+\";\"+x, val, path);\n\n else if (/^\\?\\(.*?\\)$/.test(loc)) // [?(expr)]\n\n P.walk(loc, x, val, path, function(m,l,x,v,p) { if (P.eval(l.replace(/^\\?\\((.*?)\\)$/,\"$1\"),v[m],m)) P.trace(m+\";\"+x,v,p); });\n\n else if (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)) // [start:end:step] phyton slice syntax\n\n P.slice(loc, x, val, path);\n\n }\n\n else\n\n P.store(path, val);\n\n },\n\n walk: function(loc, expr, val, path, f) {\n\n if (val instanceof Array) {\n\n for (var i=0,n=val.length; i<n; i++)\n\n if (i in val)\n\n f(i,loc,expr,val,path);\n\n }\n\n else if (typeof val === \"object\") {\n\n for (var m in val)\n\n if (val.hasOwnProperty(m))\n\n f(m,loc,expr,val,path);\n\n }\n\n },\n\n slice: function(loc, expr, val, path) {\n\n if (val instanceof Array) {\n\n var len=val.length, start=0, end=len, step=1;\n\n loc.replace(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/g, function($0,$1,$2,$3){start=parseInt($1||start);end=parseInt($2||end);step=parseInt($3||step);});\n\n start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);\n\n end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end);\n\n for (var i=start; i<end; i+=step)\n\n P.trace(i+\";\"+expr, val, path);\n\n }\n\n },\n\n eval: function(x, _v, _vname) {\n\n try { return $ && _v && eval(x.replace(/@/g, \"_v\")); }\n\n catch(e) { throw new SyntaxError(\"jsonPath: \" + e.message + \": \" + x.replace(/@/g, \"_v\").replace(/\\^/g, \"_a\")); }\n\n }\n\n };\n\n\n\n var $ = obj;\n\n if (expr && obj && (P.resultType == \"VALUE\" || P.resultType == \"PATH\")) {\n\n P.trace(P.normalize(expr).replace(/^\\$;/,\"\"), obj, \"$\");\n\n return P.result.length ? P.result : false;\n\n }\n\n}\n"
}
}
}