All files / Nodejs/lib aws-sdk-sync.ts

100% Statements 36/36
77.77% Branches 14/18
100% Functions 7/7
100% Lines 36/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82    1x           1x 4x 4x 4x 4x 2x 2x 2x       2x 1x 1x 1x   2x 2x 2x           5x       5x 5x   1x 4x   4x 4x 4x 1x   3x   3x 1x   2x             5x   5x       1x   1x       1x   4x       1x        
 
import AWS from "aws-sdk";
import { spawnSync } from "child_process";
 
// Build a function to call on a different process
// use `module.require` to keep webpack from overriding the function.
// This isn't run within the bundle
// It is stringified and run in a different process
export function invoke(service: string, method: string, config: any, params: any) {
	let AWS = module.require.call(module, "aws-sdk");
	let hasLogged = false;
	try {
		new AWS[service](config)[method](params, (err: any, data: any) => {
			Eif (!hasLogged) {
				hasLogged = true;
				console.log(`RESPONSE::${JSON.stringify({ error: err, response: data })}::RESPONSE`);
			}
		});
	} catch (err: any) {
		if (err.message.match(/is not a function/)) {
			err.message = `AWS.${service}.${method} is not a function`;
		} else Eif (err.message.match(/is not a constructor/)) {
			err.message = `AWS.${service} is not a constructor`
		}
		Eif (!hasLogged) {
			hasLogged = true;
			console.log(`RESPONSE::${JSON.stringify({ error: { message: err.message } })}::RESPONSE`);
		}
	}
};
 
function run(service: string, method: string, config: any, params: any) {
	let fn = `(${invoke.toString()})("${service}", "${method}", ${JSON.stringify(config)}, ${JSON.stringify(params)})`;
 
	// Spawn node with the function to run `node -e (()=>{})`
	// Using `RESPONSE::{}::RESPONSE` to denote the response in the output
	let child = spawnSync(process.execPath, ["-e", fn]);
	if (child.error != null) {
		// If the process had an error, throw it
		throw child.error;
	} else Eif (child.output.length > 0) {
		// Try to extract the response
		let output = child.output.join("");
		let outputJson = (child.output.join("").match(/RESPONSE::({.*})::RESPONSE/) || [])[1];
		if (outputJson == null) {
			throw new Error(`Invalid Response: ${output}`);
		} else {
			let parsedData = JSON.parse(outputJson);
			// Return the response or error
			if (parsedData.error != null) {
				throw Object.assign(new Error(parsedData.error.message), parsedData.error)
			} else {
				return parsedData.response;
			}
		}
	}
}
 
class Service<T> {
	constructor(private options?: T) { }
	protected invoke(method: string, params?: any): any {
		return run(this.constructor.name, method, this.options, params)
	}
}
 
export class SecretsManager extends Service<AWS.SecretsManager.ClientConfiguration> {
	getSecretValue(params: AWS.SecretsManager.GetSecretValueRequest): AWS.SecretsManager.GetSecretValueResponse {
		return this.invoke("getSecretValue", params);
	}
}
 
export class S3 extends Service<AWS.S3.ClientConfiguration> {
	listBuckets(): AWS.S3.ListBucketsOutput {
		return this.invoke("listBuckets");
	}
}
 
export default {
	SecretsManager,
	S3
}