fork download
  1. /**
  2.  * A description
  3.  *
  4.  * @created August 27th, 2015
  5.  * @author Luke Chavers <luke@c2cschools.com>
  6.  * @updated September 01th, 2015
  7.  * @author Prashant Tyagi <prashanttyagi@zapbuild.com>
  8.  * @copyright 2015 C2C Schools, LLC. All rights reserved.
  9.  */
  10. "use strict";
  11.  
  12. var Aag = require( "c2cs-aag-client" );
  13. var fs = require( "fs" );
  14. var Promise = require( "bluebird" );
  15. var _ = require( "underscore" );
  16. var dir = require( "node-dir" );
  17. var path = require( "path" );
  18. var apiStack = [];
  19. var aagConfig;
  20.  
  21. // Load AWS Settings
  22. aagConfig = {
  23. accessKeyId : process.env.AWS_ACCESS_KEY || "AKIAIRA267B3CP6IIGUA",
  24. secretAccessKey : process.env.AWS_SECRET_KEY || "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",
  25. region : process.env.AWS_REGION || "us-east-1"
  26. //apiId : process.env.AWS_API_ID || "893szowwmb",
  27. //apiRootResource : process.env.AWS_ROOT_RESOURCE || "u455nq7412"
  28. };
  29.  
  30.  
  31. function checkDirExist ( dir ) {
  32. var stats = fs.lstatSync( dir );
  33.  
  34. if( stats.isDirectory() ) {
  35. return true;
  36. }
  37. return false;
  38. }
  39.  
  40. /**
  41.  * Entry Point For publish api's to AAG
  42.  *
  43.  * @param {Object} object
  44.  * @param {Object} context
  45.  * @param {function} callback This callback function is passed from different stages
  46.  * @returns {void}
  47.  */
  48.  
  49. module.exports = function ( object, context, cb ) {
  50.  
  51. //validations
  52. if( !object.api ){
  53. cb( new Error( "API ID is required." ), true );
  54. } else {
  55. aagConfig.apiId = object.api;
  56. }
  57.  
  58. if( !object.configRoot ){
  59. object.configRoot = "apis/spec/";
  60. context.out( "Error: configRoot is not defined, default is 'apis/spec' " + '\n', 'warn' );
  61. }
  62.  
  63. if( !object.publish ){
  64. object.publish = "v3";
  65. context.out( "Error: Publish Stage is not defined, default is 'v3' " + '\n', 'warn' );
  66. }
  67.  
  68. //APIs path
  69. var spath = object.configRoot + object.publish;
  70. var dirPath = path.join( context.dataDir, spath );
  71.  
  72. //Set config
  73. Aag.aagConfig = aagConfig;
  74.  
  75.  
  76. //Check if provided path exist
  77. var exist = checkDirExist( dirPath );
  78.  
  79. if(!exist) {
  80. cb( new Error( "Provided path doesn't exist: " + spath ), true );
  81. }
  82.  
  83.  
  84. //read all subdirectories
  85. dir.subdirs( dirPath, function( err, subdirs ) {
  86.  
  87. if ( err ) {
  88. cb( err, true );
  89. }
  90.  
  91. //Fetch all api resources first and store them into stack
  92. Aag.getApiResources( object.api ).then( function( res ) {
  93.  
  94. if( Array.isArray( res._embedded.item ) ) { //check if result is object or array
  95.  
  96. var j = 0;
  97. _.each( res._embedded.item, function( value, index ){ //if array, means muliple records here
  98.  
  99. apiStack[ value.path ] = value.id; //add it in apiStack stack
  100. j++;
  101.  
  102. if( j == res._embedded.item.length ) { //if end of loop
  103.  
  104. resourceLoop( object, context, cb ); //traverse through all resources
  105.  
  106. }
  107.  
  108. });
  109.  
  110. } else {
  111.  
  112. apiStack[ res._embedded.item.path ] = res._embedded.item.id; //only root resource exist, add it in apiStack stack
  113. resourceLoop( object, context, cb ); //traverse through all resources
  114.  
  115. }
  116.  
  117. }).catch( function( err ) {
  118.  
  119. context.out( "Error: While getting all resources from given API ID : " + object.api + "\n", "error" );
  120. cb( new Error( "Error: While getting all resources from given API ID : " + object.api ), true );
  121.  
  122. });
  123.  
  124.  
  125. var i = 0;
  126. var subdirCount = subdirs.length; //no. of subdirectories
  127.  
  128. //iterate through all sub directories
  129. function resourceLoop( object, context, cb, i ) {
  130.  
  131. if( typeof i === "undefined" ) {
  132. i = 0;
  133. }
  134.  
  135. var configFile = subdirs[i] + "/endpoint-config.json";
  136. var templateFile = subdirs[i] + "/response-mapping-template.txt";
  137. var configData = "";
  138. var templateData = "";
  139.  
  140. //check if config file exist
  141. if ( fs.existsSync( configFile ) ) {
  142.  
  143. configData = JSON.parse( fs.readFileSync( configFile, "utf-8" ));
  144.  
  145. }
  146.  
  147. //check if template file exist
  148. if ( fs.existsSync( templateFile ) ) {
  149.  
  150. templateData = fs.readFileSync( templateFile, "utf-8" );
  151.  
  152. }
  153.  
  154. //So now we have all data to enter an API point
  155. if( i < subdirCount ) { //check if end of loop
  156.  
  157. if( configData ) { //if config data present
  158.  
  159. if( apiStack[configData.resourcePath] ) { //check if api endpoint exist
  160.  
  161. //ALready exist, remove it first
  162. Aag.deleteResource( apiStack[configData.resourcePath] ).then( function( res ) {
  163.  
  164. //remove resource from apiStach array also
  165. var index = apiStack.indexOf( apiStack[configData.resourcePath] );
  166. if ( index > -1 ) {
  167. apiStack.splice( index, 1 );
  168. }
  169.  
  170. addApi( object, context, cb, configData, templateData ).then( function( res ) { // add api endpoint
  171.  
  172. context.out( "Endpoint added successfully: " + configData.resourcePath + "\n", "stdout" );
  173. resourceLoop( object, context, cb, i+1 ); //move to next resource
  174.  
  175. }).catch( function( err ) {
  176.  
  177. context.out( "Endpoint insertion failed: " + configData.resourcePath + "\n " + err + "\n", "error" );
  178. resourceLoop( object, context, cb, i+1 ); //move to next resource
  179.  
  180. });
  181.  
  182. });
  183.  
  184. } else {
  185.  
  186. //not exist, add new
  187. addApi( object, context, cb, configData, templateData ).then( function( res ) { // add api endpoint
  188.  
  189. context.out( "Endpoint added successfully: " + configData.resourcePath + "\n", "stdout" );
  190. resourceLoop( object, context, cb, i+1 ); //move to next resource
  191.  
  192. }).catch( function( err ) {
  193.  
  194. context.out( "Endpoint insertion failed: " + configData.resourcePath + "\n " + err + "\n", "error" );
  195. resourceLoop( object, context, cb, i+1 ); //move to next resource
  196.  
  197. });
  198.  
  199. }
  200.  
  201. } else {
  202.  
  203. resourceLoop( object, context, cb, i+1 ); //move to next resource
  204.  
  205. }
  206.  
  207. } else {
  208.  
  209. //API Deployment at the end
  210. Aag.createDeployment( object.publish ).then( function( res ) {
  211.  
  212. context.out( "\n" + "Deployment of API's on AWS API Gateway is successful " + "\n", "message" );
  213. cb( null, true );
  214.  
  215. }).catch( function( err ) {
  216.  
  217. context.out( "\n" + "Deployment of API's on AWS API Gateway is failed: " + "\n " + err + "\n", "error" );
  218. cb( err, true );
  219.  
  220. });
  221.  
  222. apiStack = [];
  223. }
  224.  
  225. };
  226.  
  227. });
  228.  
  229. };
  230.  
  231.  
  232. /*
  233.  * Get resource array
  234.  *
  235.  * Example : splitResource( "/SanctioningBody/{sanctioningBodyId}/SanctioningCategories" )
  236.  * Output :
  237.  * [
  238.  * "/SanctioningBody",
  239.  * "/SanctioningBody/{sanctioningBodyId}",
  240.  * "/SanctioningBody/{sanctioningBodyId}/SanctioningCategories"
  241.  * ]
  242.  */
  243. function splitResource( resource ) {
  244.  
  245. var arr = resource.split("/");
  246. var resources = [];
  247.  
  248. for( var i = 1; i < arr.length; i++ ) {
  249. if( i != 1 ) {
  250. resources.push( resources[i-2] + "/" + arr[i] );
  251. } else {
  252. resources.push( "/" + arr[i] );
  253. }
  254. }
  255.  
  256. return resources;
  257.  
  258. }
  259.  
  260.  
  261. /*
  262.  * Add all parent resources of provided resource, if not present
  263.  *
  264.  */
  265. function addAllResourcePoints( resources, count, i, callback ) {
  266.  
  267. if( typeof i === "undefined" ) {
  268. i = 0;
  269. }
  270.  
  271. if( i < count ) { //check if end of loop
  272.  
  273. if( !apiStack[resources[i]] ) {
  274. var resourceId = "";
  275.  
  276. //Check for parent resource ID
  277. if( i == 0 ) {
  278.  
  279. resourceId = apiStack['/']; //set root id as parent resourceId
  280.  
  281. } else {
  282.  
  283. resourceId = apiStack[resources[i-1]]; //set previous record id as parent resourceId
  284.  
  285. }
  286.  
  287. var last = resources[i].substring(resources[i].lastIndexOf("/") + 1, resources[i].length);
  288.  
  289. // 1) createResource( { "pathPart" : "test" }, "ID of parent resopurce" );
  290. var a = Aag.createResource( { "pathPart" : last }, resourceId ).then( function(res){
  291.  
  292. //set that resource into stack
  293. apiStack[resources[i]] = res.id;
  294.  
  295. addAllResourcePoints( resources, count, i+1, callback );
  296.  
  297. });
  298.  
  299. } else {
  300.  
  301. addAllResourcePoints( resources, count, i+1, callback );
  302.  
  303. }
  304.  
  305. } else {
  306.  
  307. //loop end
  308. if( apiStack[resources[i-1]] ) { //pass resourceId of provided resource
  309. callback( apiStack[resources[i-1]], false );
  310. } else {
  311. callback( "", new Error( "Resource Id not found." ) );
  312. }
  313.  
  314. }
  315.  
  316. }
  317.  
  318.  
  319. /*
  320.  * Add api endpoint
  321.  *
  322.  *
  323.  */
  324. function addApi( object, context, cb, configData, templateData ) {
  325.  
  326. var resourceId = apiStack["/"]; //set resourceId as root resourceId
  327. var resource = configData.resourcePath;
  328.  
  329. return new Promise( function( resolve, reject ) {
  330.  
  331. var resources = splitResource(resource);
  332. var count = resources.length;
  333.  
  334.  
  335. //1) Add api resource and enter them into stack
  336. addAllResourcePoints( resources, count, 0, function( res, err ){
  337.  
  338. if( err ) {
  339. cb( err, true );
  340. }
  341.  
  342. resourceId = res;
  343.  
  344. var requestData = {
  345. "authorizationType" : "",
  346. "apiKeyRequired" : true,
  347. "requestParameters" : configData.requestMethodParameters
  348. }
  349.  
  350. // 2) Create resource method
  351. Aag.createResourceMethod( configData.method, requestData, resourceId ).then( function( res ){
  352.  
  353. return res;
  354.  
  355. }).then( function( res ) {
  356.  
  357. // 3) Create resource method response model
  358. return Aag.attachMethodResponseModel( configData.method, configData.responseModel, resourceId, "200" ).then( function( res ){
  359.  
  360. return res;
  361.  
  362. });
  363.  
  364. }).then( function( res ) {
  365.  
  366. var requestData = {
  367. "type" : configData.type,
  368. "httpMethod" : configData.method,
  369. "uri" : configData.endpointUrl,
  370. "requestParameters" : configData.requestIntegrationParameters
  371. }
  372.  
  373. // 4) Create resource method integration
  374. return Aag.addMethodIntegration( configData.method, requestData, resourceId ).then( function( res ){
  375.  
  376. return res;
  377.  
  378. });
  379.  
  380. }).then( function( res ) {
  381.  
  382. //5) Attach Integration model for resource method
  383. return Aag.attachIntegrationResponseModel( configData.method, resourceId, "200" ).then( function( res ){
  384.  
  385. return res;
  386.  
  387. });
  388.  
  389. }).then( function( res ) {
  390.  
  391. //6) Attach Integration response model for 200
  392. if( templateData ) {
  393.  
  394. return Aag.attachIntegrationResponseTemplate( configData.method, resourceId, templateData, "200" ).then( function( res ){
  395.  
  396. resolve( res );
  397.  
  398. });
  399.  
  400. } else {
  401.  
  402. resolve( true );
  403.  
  404. }
  405.  
  406. }).catch( function( err ) {
  407.  
  408. reject( err );
  409.  
  410. });
  411.  
  412. });
  413.  
  414. });
  415.  
  416. }
  417.  
Runtime error #stdin #stdout #stderr 0.13s 52104KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
module.js:338
    throw err;
          ^
Error: Cannot find module 'c2cs-aag-client'
    at Function.Module._resolveFilename (module.js:336:15)
    at Function.Module._load (module.js:278:25)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/home/XnhfZA/prog.js:12:13)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)