Last active
January 8, 2018 17:11
-
-
Save mrosata/4b478ab5ee3ab03c87d32ee321ef8235 to your computer and use it in GitHub Desktop.
Generates code to wrap entire AWS service apis as functions or methods returning Promises. Setup: `yarn add ramda yargs`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/node | |
//////////////////////////////////////////////////////////////////////////////// | |
//// Create AWS Service Promisified Functions | |
//// @author Michael Rosata | |
//// | |
//// @dependencies ramda, yargs | |
//// | |
//// @desc | |
//// Returns the code that would wrap every method from one AWS Service into | |
//// functions that return Promises rather than those returning Node style | |
//// callbacks. | |
//// The new functions are named similar to their original counterparts. | |
//// IE: | |
//// S3.getBucket() --> s3GetBucket() | |
//// It can also generate an entire module.export = {...} for the service. | |
//// in which case `s3getBucket` becomes `s3.getBucket` | |
//// | |
//// @uses | |
//// node ./denode-aws-service-code.js --service s3 | |
//// node ./denode-aws-service-code.js --service s3 --as-export | |
//// node ./denode-aws-service-code.js --service sqs --namespace SQS | |
//// node ./denode-aws-service-code.js --service sqs --promisify customFnName | |
//// | |
const AWS = require('aws-sdk') | |
const argv = require('yargs').argv | |
const { | |
map, | |
filter, | |
complement, | |
pipe, | |
either, | |
equals, | |
apply, | |
join, | |
propOr, | |
toUpper, | |
} = require('ramda') | |
//// | |
//// Command Line Arguments | |
const SERVICE = argv.service || argv.s || '' | |
const NS = argv.namespace || argv.ns || toUpper(SERVICE) | |
const AS_EXPORT = Boolean(argv.asExport || argv.e) | |
const PROMISIFY = argv.promisify || argv.p || 'denodify' | |
//// | |
//// Utility Functions | |
//// | |
// capitalize :: | |
const capitalize = | |
s => | |
`${s.substr(0,1).toUpperCase()}${s.substr(1)}` | |
// getCode :: | |
const getCode = | |
(ns, promisify) => | |
methods => | |
methods.map(name => `const ${ns}${capitalize(name)} = ${promisify}(${ns}.${name}, ${ns})`) | |
// getExport :: | |
const getExportCode = | |
(ns, promisify) => | |
(methods = []) => [ | |
`module.exports = {`, // Declare and open object literal | |
...methods.map(name => ` ${name}: ${promisify}(${ns}.${name}, ${ns}),`), | |
'}', // closed object literal | |
] | |
// notApiOrConstructor :: | |
const notApiOrConstructor = complement( | |
either( | |
equals('serviceIdentifier'), | |
either(equals('api'), equals('constructor')) | |
)) | |
//// | |
//// Main Code | |
//// | |
/** | |
* Create Code which would promisify (denodify) an AWS service | |
* into either a series of declared functions or as one namespace | |
* that essentially has the same collection of methods as the | |
* service being denodified | |
* | |
* @param {string} serviceName - name of service, ie: 's3', 'sqs'. | |
* @param {string} [serviceNS] - namespace of service on AWS object. By | |
* default it assumes the `serviceName` capitalized. | |
* @param {string} [promisify] - name of the promisify function. | |
* @param {boolean} [asExport] - default false, create as object instead | |
* of having all individual functions. | |
*/ | |
function denodeAwsServiceCode(serviceName, serviceNS = toUpper(serviceName), promisify = 'denodify', asExport = false) { | |
// Create the service so we can get the method names from its __proto__ | |
const service = new AWS[serviceNS]() | |
// Depending on whether the code will be one namespace or many functions, we need different builder | |
const codeBuilder = asExport ? getExportCode : getCode | |
// Get the keys, filter unwanted properties, build the code | |
return pipe( | |
x => Reflect.ownKeys(x.__proto__), | |
filter(notApiOrConstructor), | |
codeBuilder(serviceName, promisify), | |
join('\n') | |
)(service) | |
} | |
//// | |
//// If Command Line Arguments Passed, then we shall execute the function | |
//// to to build and output code that promisifies the AWS 'SERVICE' service | |
if (SERVICE && NS) { | |
const theCode = denodeAwsServiceCode(SERVICE, NS, PROMISIFY, AS_EXPORT) | |
console.log( | |
`/**\ | |
\n * AWS SERVICE ${NS} AS PROMISE RETURNING FUNCTIONS\ | |
\n */\ | |
\n\const AWS = require('aws-sdk') | |
\n\ | |
\n// denodify ::\ | |
\nconst denodify =\ | |
\n (fn, context = null) =>\ | |
\n (...args) =>\ | |
\n new Promise((resolve, reject) => {\ | |
\n fn.call(context, ...args, (err, data) => {\ | |
\n if (err) return reject(err)\ | |
\n return resolve(data)\ | |
\n })\ | |
\n })\ | |
\n\ | |
\n////\ | |
\n//// Actual AWS Service:${NS}:\ | |
\nconst ${SERVICE} = new AWS.${NS}({/*..config..*/})\ | |
\n\ | |
\n////\ | |
\n//// Denodified Versions of ${SERVICE} API methods\ | |
\n${theCode}\ | |
\n` | |
) | |
} | |
module.exports = denodeAwsServiceCode |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment