mirror of
https://github.com/serverless/serverless.git
synced 2026-01-25 15:07:39 +00:00
multi stage support
This commit is contained in:
parent
26b85cb235
commit
daebf89840
7
.gitignore
vendored
7
.gitignore
vendored
@ -6,12 +6,17 @@
|
||||
*.pid
|
||||
*.gz
|
||||
|
||||
**/.idea
|
||||
.DS_Store
|
||||
.tmp
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
logs
|
||||
results
|
||||
.DS_Store
|
||||
npm-debug.log
|
||||
.env
|
||||
.adminenv
|
||||
|
||||
site/public/libs
|
||||
site/node_modules
|
||||
|
||||
147
aws/data-model-cf.json
Normal file
147
aws/data-model-cf.json
Normal file
@ -0,0 +1,147 @@
|
||||
{
|
||||
"AWSTemplateFormatVersion": "2010-09-09",
|
||||
"Parameters": {
|
||||
"aaaPrefix": {
|
||||
"Type": "String",
|
||||
"Default": "test",
|
||||
"AllowedValues": [
|
||||
"me",
|
||||
"test",
|
||||
"prod"
|
||||
]
|
||||
},
|
||||
"aaaDefaultDynamoRWThroughput": {
|
||||
"Type": "String",
|
||||
"Default": "1"
|
||||
},
|
||||
"aaaProjectName": {
|
||||
"Type": "String",
|
||||
"Default": "jaws",
|
||||
"AllowedValues": [
|
||||
"jaws"
|
||||
]
|
||||
},
|
||||
"HostedZoneName": {
|
||||
"Type": "String",
|
||||
"Default": "doapps.co"
|
||||
},
|
||||
"imagesReadThroughput": {
|
||||
"Type": "String",
|
||||
"Default": "1"
|
||||
},
|
||||
"imagesWriteThroughput": {
|
||||
"Type": "String",
|
||||
"Default": "1"
|
||||
}
|
||||
},
|
||||
"Resources": {
|
||||
"images": {
|
||||
"Type": "AWS::DynamoDB::Table",
|
||||
"Properties": {
|
||||
"TableName": {
|
||||
"Fn::Join": [
|
||||
"-",
|
||||
[
|
||||
{
|
||||
"Ref": "aaaPrefix"
|
||||
},
|
||||
{
|
||||
"Ref": "aaaProjectName"
|
||||
},
|
||||
"images"
|
||||
]
|
||||
]
|
||||
},
|
||||
"AttributeDefinitions": [
|
||||
{
|
||||
"AttributeName": "bucketKey",
|
||||
"AttributeType": "S"
|
||||
}
|
||||
],
|
||||
"KeySchema": [
|
||||
{
|
||||
"AttributeName": "bucketKey",
|
||||
"KeyType": "HASH"
|
||||
}
|
||||
],
|
||||
"ProvisionedThroughput": {
|
||||
"ReadCapacityUnits": {
|
||||
"Ref": "imagesReadThroughput"
|
||||
},
|
||||
"WriteCapacityUnits": {
|
||||
"Ref": "imagesWriteThroughput"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"users": {
|
||||
"Type": "AWS::DynamoDB::Table",
|
||||
"DependsOn": "images",
|
||||
"Properties": {
|
||||
"TableName": {
|
||||
"Fn::Join": [
|
||||
"-",
|
||||
[
|
||||
{
|
||||
"Ref": "aaaPrefix"
|
||||
},
|
||||
{
|
||||
"Ref": "aaaProjectName"
|
||||
},
|
||||
"users"
|
||||
]
|
||||
]
|
||||
},
|
||||
"AttributeDefinitions": [
|
||||
{
|
||||
"AttributeName": "_id",
|
||||
"AttributeType": "S"
|
||||
},
|
||||
{
|
||||
"AttributeName": "created",
|
||||
"AttributeType": "N"
|
||||
}
|
||||
],
|
||||
"KeySchema": [
|
||||
{
|
||||
"AttributeName": "_id",
|
||||
"KeyType": "HASH"
|
||||
},
|
||||
{
|
||||
"AttributeName": "created",
|
||||
"KeyType": "RANGE"
|
||||
}
|
||||
],
|
||||
"ProvisionedThroughput": {
|
||||
"ReadCapacityUnits": {
|
||||
"Ref": "aaaDefaultDynamoRWThroughput"
|
||||
},
|
||||
"WriteCapacityUnits": {
|
||||
"Ref": "aaaDefaultDynamoRWThroughput"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"imagesBucket": {
|
||||
"Type": "AWS::S3::Bucket",
|
||||
"DeletionPolicy": "Delete",
|
||||
"Properties": {
|
||||
"BucketName": {
|
||||
"Fn::Join": [
|
||||
"",
|
||||
[
|
||||
{
|
||||
"Ref": "aaaProjectName"
|
||||
},
|
||||
"-images.",
|
||||
{
|
||||
"Ref": "HostedZoneName"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"AccessControl": "PublicRead"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
166
aws/perms-cf.json
Normal file
166
aws/perms-cf.json
Normal file
@ -0,0 +1,166 @@
|
||||
{
|
||||
"AWSTemplateFormatVersion": "2010-09-09",
|
||||
"Description": "JAWS",
|
||||
"Parameters": {
|
||||
"aaaStage": {
|
||||
"Type": "String",
|
||||
"Default": "test"
|
||||
},
|
||||
"aaaDataModelPrefix": {
|
||||
"Type": "String",
|
||||
"Default": "test",
|
||||
"AllowedValues": [
|
||||
"test",
|
||||
"prod"
|
||||
]
|
||||
},
|
||||
"aaaProjectName": {
|
||||
"Type": "String",
|
||||
"Default": "jaws",
|
||||
"AllowedValues": [
|
||||
"jaws"
|
||||
]
|
||||
}
|
||||
},
|
||||
"Resources": {
|
||||
"LambdaRole": {
|
||||
"Type": "AWS::IAM::Role",
|
||||
"Properties": {
|
||||
"AssumeRolePolicyDocument": {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Service": [
|
||||
"lambda.amazonaws.com"
|
||||
]
|
||||
},
|
||||
"Action": [
|
||||
"sts:AssumeRole"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"Path": "/",
|
||||
"Policies": [
|
||||
{
|
||||
"PolicyName": "CloudWatch",
|
||||
"PolicyDocument": {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"logs:CreateLogGroup",
|
||||
"logs:CreateLogStream",
|
||||
"logs:PutLogEvents"
|
||||
],
|
||||
"Resource": "arn:aws:logs:*:*:*"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"PolicyName": "s3Write",
|
||||
"PolicyDocument": {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"s3:Get*",
|
||||
"s3:List*",
|
||||
"s3:Put*"
|
||||
],
|
||||
"Resource": [
|
||||
{
|
||||
"Fn::Join": [
|
||||
"",
|
||||
[
|
||||
"arn:aws:s3:::",
|
||||
{
|
||||
"Ref": "aaaProjectName"
|
||||
},
|
||||
"-images/",
|
||||
{
|
||||
"Ref": "aaaDataModelPrefix"
|
||||
},
|
||||
"*"
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"Effect": "Allow"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"PolicyName": "DynamoWrite",
|
||||
"PolicyDocument": {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"dynamodb:BatchGetItem",
|
||||
"dynamodb:BatchWriteItem",
|
||||
"dynamodb:DeleteItem",
|
||||
"dynamodb:DescribeTable",
|
||||
"dynamodb:Get*",
|
||||
"dynamodb:List*",
|
||||
"dynamodb:PutItem",
|
||||
"dynamodb:Query",
|
||||
"dynamodb:Scan",
|
||||
"dynamodb:UpdateItem",
|
||||
"dynamodb:UpdateTable"
|
||||
],
|
||||
"Resource": [
|
||||
{
|
||||
"Fn::Join": [
|
||||
"",
|
||||
[
|
||||
"arn:aws:dynamodb:us-east-1:",
|
||||
{
|
||||
"Ref": "AWS::AccountId"
|
||||
},
|
||||
":table/",
|
||||
{
|
||||
"Ref": "aaaDataModelPrefix"
|
||||
},
|
||||
{
|
||||
"Ref": "aaaProjectName"
|
||||
},
|
||||
"-users*"
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"Fn::Join": [
|
||||
"",
|
||||
[
|
||||
"arn:aws:dynamodb:us-east-1:",
|
||||
{
|
||||
"Ref": "AWS::AccountId"
|
||||
},
|
||||
":table/",
|
||||
{
|
||||
"Ref": "aaaDataModelPrefix"
|
||||
},
|
||||
{
|
||||
"Ref": "aaaProjectName"
|
||||
},
|
||||
"-images*"
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
62
cli/bin/jaws
62
cli/bin/jaws
@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var JAWS = require('../lib/main.js');
|
||||
var JAWS = require('../lib/main.js');
|
||||
var program = require('commander');
|
||||
var shortid = require('shortid');
|
||||
|
||||
var Q = require('q');
|
||||
|
||||
|
||||
/**
|
||||
@ -12,12 +12,32 @@ var shortid = require('shortid');
|
||||
*/
|
||||
|
||||
program
|
||||
.version(JAWS.version)
|
||||
.command( 'deploy' )
|
||||
.description( 'Deploy your application to Amazon Lambda' )
|
||||
.action( function( prg ) {
|
||||
JAWS.deploy( prg );
|
||||
});
|
||||
.version(JAWS.version)
|
||||
.command('deploy <stage>')
|
||||
.description('Deploy your application to Amazon Lambda')
|
||||
.action(function (stage, prg) {
|
||||
try {
|
||||
JAWS.deploy(stage)
|
||||
.then(function (functionArns) {
|
||||
console.log('****** JAWS: Success! - Your Lambda Function has been successfully deployed to AWS Lambda. This Lambda Function\'s ARNs are: ');
|
||||
console.log("\t", functionArns.join(', '));
|
||||
process.exit(0);
|
||||
})
|
||||
.fail(function (err) {
|
||||
console.error(err, err.stack);
|
||||
process.exit(-1);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err, err.stack);
|
||||
process.exit(-1);
|
||||
}
|
||||
})
|
||||
.on('--help', function () {
|
||||
console.log(' Examples:');
|
||||
console.log("\n\tdeploy prod");
|
||||
console.log("\n\tdeploy test");
|
||||
console.log();
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
@ -26,12 +46,12 @@ program
|
||||
*/
|
||||
|
||||
program
|
||||
.version( JAWS.version )
|
||||
.command( 'run' )
|
||||
.description( 'Run your Amazon Lambda application locally' )
|
||||
.action( function( prg ) {
|
||||
JAWS.run( prg );
|
||||
});
|
||||
.version(JAWS.version)
|
||||
.command('run')
|
||||
.description('Run your Amazon Lambda application locally')
|
||||
.action(function (prg) {
|
||||
JAWS.run();
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
@ -40,12 +60,12 @@ program
|
||||
*/
|
||||
|
||||
program
|
||||
.version( JAWS.version )
|
||||
.command( 'server' )
|
||||
.description( 'Start your server' )
|
||||
.action( function( prg ) {
|
||||
JAWS.server( prg );
|
||||
});
|
||||
.version(JAWS.version)
|
||||
.command('server')
|
||||
.description('Start your server')
|
||||
.action(function (prg) {
|
||||
JAWS.server();
|
||||
});
|
||||
|
||||
|
||||
program.parse( process.argv );
|
||||
program.parse(process.argv);
|
||||
|
||||
22
cli/jaws.yml
Normal file
22
cli/jaws.yml
Normal file
@ -0,0 +1,22 @@
|
||||
version: 0.0
|
||||
jaws:
|
||||
deploy:
|
||||
envS3Location: lambdadeploy.doapps.com/jaws/env/ #will read stage (prod,test,developername etc) containing contents of temp.env
|
||||
regions:
|
||||
- us-east-1
|
||||
packageExcludes: #see man page on zip -x. Ex: -x *.DS_Store *.svn*
|
||||
- "*.git/*"
|
||||
- "node_modules/chai/*"
|
||||
- "node_modules/mocha/*"
|
||||
- "tests/*"
|
||||
packageFiles: #list of files/dirs passed to zip, relative to lib dir
|
||||
- controllers
|
||||
- lib
|
||||
- node_modules
|
||||
- config.js
|
||||
- index.js
|
||||
- .env # created by aws-deployment
|
||||
iamRoles:
|
||||
test: arn:aws:iam::28933237018:role/test-jaws_lambda_role
|
||||
prod: arn:aws:iam::28933237018:role/prod-jaws_lambda_role
|
||||
me: arn:aws:iam::28933237018:role/me-jaws_lambda_role
|
||||
138
cli/lib/main.js
138
cli/lib/main.js
@ -3,23 +3,22 @@
|
||||
*/
|
||||
|
||||
|
||||
var aws = require('aws-sdk');
|
||||
var exec = require('child_process').exec;
|
||||
var fs = require('fs');
|
||||
var os = require('os');
|
||||
var sys = require('sys');
|
||||
var aws = require('aws-sdk');
|
||||
var exec = require('child_process').exec;
|
||||
var fs = require('fs');
|
||||
var os = require('os');
|
||||
var packageJson = require('./../package.json');
|
||||
var path = require('path');
|
||||
var async = require('async');
|
||||
var zip = new require('node-zip')();
|
||||
var wrench = require('wrench');
|
||||
var jsonfile = require('jsonfile');
|
||||
var del = require('del');
|
||||
var moment = require('moment');
|
||||
var path = require('path');
|
||||
var async = require('async');
|
||||
var zip = new require('node-zip')();
|
||||
var wrench = require('wrench');
|
||||
var moment = require('moment');
|
||||
var yaml = require('js-yaml');
|
||||
var Q = require('q');
|
||||
|
||||
|
||||
var JAWS = function() {
|
||||
this.version = packageJson.version;
|
||||
var JAWS = function () {
|
||||
this.version = packageJson.version;
|
||||
this.configYml = yaml.safeLoad(fs.readFileSync(__dirname + '/../jaws.yml', 'utf8')).jaws;
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -28,7 +27,7 @@ var JAWS = function() {
|
||||
* JAWS: Run Lambda Function Locally
|
||||
*/
|
||||
|
||||
JAWS.prototype.run = function(program) {
|
||||
JAWS.prototype.run = function () {
|
||||
|
||||
console.log('****** JAWS: Running Lambda Function Locally...');
|
||||
|
||||
@ -36,26 +35,26 @@ JAWS.prototype.run = function(program) {
|
||||
if (!fs.existsSync(process.cwd() + '/index.js')) return console.log('****** JAWS: Error - You must be in the root directory of your Lambda function to run it locally.');
|
||||
|
||||
var extension = require(process.cwd() + '/index.js');
|
||||
var event = require(process.cwd() + '/event.json');
|
||||
var event = require(process.cwd() + '/event.json');
|
||||
|
||||
// Run Handler
|
||||
this._runHandler(extension.handler, event);
|
||||
};
|
||||
|
||||
|
||||
JAWS.prototype._runHandler = function(handler, event) {
|
||||
JAWS.prototype._runHandler = function (handler, event) {
|
||||
var context = {
|
||||
succeed: function(result) {
|
||||
succeed: function (result) {
|
||||
console.log('****** JAWS: Lambda Finished Successfully: ');
|
||||
console.log(result);
|
||||
return process.exit(0);
|
||||
},
|
||||
fail: function(error) {
|
||||
fail: function (error) {
|
||||
console.log('****** JAWS: Lambda Returned An Error: ');
|
||||
console.log(error);
|
||||
return process.exit(0);
|
||||
},
|
||||
done: function(error, result) {
|
||||
done: function (error, result) {
|
||||
|
||||
if (error) {
|
||||
console.log('****** JAWS: Lambda Returned An Error: ');
|
||||
@ -75,48 +74,51 @@ JAWS.prototype._runHandler = function(handler, event) {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* JAWS: Deploy Lambda Function
|
||||
*/
|
||||
|
||||
JAWS.prototype.deploy = function(program) {
|
||||
JAWS.prototype.deploy = function (stage) {
|
||||
var deferred = Q.defer();
|
||||
|
||||
console.log('****** JAWS: Deploying your Lambda function to AWS Lambda. This could take a few minutes...');
|
||||
|
||||
// Require ENV Variables
|
||||
require('dotenv').config({
|
||||
path: process.cwd() + '/node_modules/app-lib/.env'
|
||||
path: process.cwd() + '/node_modules/app-lib/.adminenv'
|
||||
});
|
||||
|
||||
// Defaults
|
||||
var _this = this;
|
||||
var fs = require('fs');
|
||||
var _this = this;
|
||||
var previous = '/';
|
||||
var regions = process.env.AWS_LAMBDA_REGIONS.split(',');
|
||||
var codeDirectory = os.tmpDir() + process.env.LAMBDA_FUNCTION_NAME + '-' + moment().unix();
|
||||
var regions = this.configYml.deploy.regions;
|
||||
|
||||
// Get Lambda Config
|
||||
if (!fs.existsSync(process.cwd() + '/lambda.json')) return console.log('****** JAWS Error: lambda.json is missing in this folder');
|
||||
var lambda_config = require(process.cwd() + '/lambda.json');
|
||||
var lambda_config = require(process.cwd() + '/lambda.json');
|
||||
lambda_config.FunctionName = stage + "_" + lambda_config.FunctionName;
|
||||
|
||||
var codeDirectory = os.tmpDir() + lambda_config.FunctionName + '-' + moment().unix();
|
||||
|
||||
// Get path to "lib" folder
|
||||
var lib_path = false;
|
||||
for (i = 0; i < 20; i++) {
|
||||
for (var i = 0; i < 20; i++) {
|
||||
previous = previous + '../';
|
||||
if (fs.existsSync(process.cwd() + previous + 'lib/index.js')) {
|
||||
lib_path = previous + 'lib';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!lib_path) return console.log('***** JAWS Error: Can\'t find your lib folder. Did you rename it or create folders over 20 levels deep in your api folder?');
|
||||
if (!lib_path) {
|
||||
return Q.fcall(function () {
|
||||
throw new Error('***** JAWS Error: Can\'t find your lib folder. Did you rename it or create folders over 20 levels deep in your api folder?')
|
||||
});
|
||||
}
|
||||
|
||||
// Copy Lambda Folder To System Temp Directory
|
||||
wrench.copyDirSyncRecursive(process.cwd(), codeDirectory, {
|
||||
forceDelete: true,
|
||||
include: function(name, more) {
|
||||
include: function (name, more) {
|
||||
if (name === '.git') return false;
|
||||
else return true;
|
||||
}
|
||||
@ -129,15 +131,13 @@ JAWS.prototype.deploy = function(program) {
|
||||
wrench.copyDirSyncRecursive(process.cwd() + lib_path, codeDirectory + '/node_modules/app-lib');
|
||||
|
||||
// Zip function
|
||||
_this._zip(program, codeDirectory, function(err, buffer) {
|
||||
_this._zip(lambda_config.FunctionName, codeDirectory, function (err, buffer) {
|
||||
|
||||
console.log('****** JAWS: Zipping up your Lambda Function\'s files...');
|
||||
|
||||
async.map(regions, function(region, cb) {
|
||||
async.map(regions, function (region, cb) {
|
||||
|
||||
aws.config.update({
|
||||
accessKeyId: process.env.AWS_ADMIN_ACCESS_KEY,
|
||||
secretAccessKey: process.env.AWS_ADMIN_SECRET_ACCESS_KEY,
|
||||
aws.config.update({ //SDK auto-loads creds from process.env.AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
|
||||
region: region
|
||||
});
|
||||
|
||||
@ -152,7 +152,7 @@ JAWS.prototype.deploy = function(program) {
|
||||
},
|
||||
FunctionName: lambda_config.FunctionName,
|
||||
Handler: lambda_config.Handler ? lambda_config.Handler : 'index.handler',
|
||||
Role: lambda_config.Role ? lambda_config.Role : process.env.AWS_LAMBDA_ROLE_ARN,
|
||||
Role: lambda_config.Role ? lambda_config.Role : _this.configYml.iamRoles[stage],
|
||||
Runtime: lambda_config.Runtime,
|
||||
Description: lambda_config.Description ? lambda_config.Description : 'A Lambda function that was created with the JAWS framework',
|
||||
MemorySize: lambda_config.MemorySize,
|
||||
@ -162,9 +162,11 @@ JAWS.prototype.deploy = function(program) {
|
||||
// Check If Lambda Function Exists Already
|
||||
lambda.getFunction({
|
||||
FunctionName: lambda_config.FunctionName
|
||||
}, function(err, data) {
|
||||
}, function (err, data) {
|
||||
|
||||
if (err && err.code !== 'ResourceNotFoundException') return console.log(err, err.stack);
|
||||
if (err && err.code !== 'ResourceNotFoundException') {
|
||||
return deferred.reject(err);
|
||||
}
|
||||
|
||||
if (!data || !data.Code) {
|
||||
|
||||
@ -173,10 +175,10 @@ JAWS.prototype.deploy = function(program) {
|
||||
* Create New Lambda Function
|
||||
*/
|
||||
|
||||
console.log('****** JAWS: Uploading your Lambda Function to AWS Lambda with these parameters: ');
|
||||
console.log('****** JAWS: Uploading your Lambda function to ' + stage + ' with these parameters: ');
|
||||
console.log(params);
|
||||
|
||||
lambda.createFunction(params, function(err, data) {
|
||||
lambda.createFunction(params, function (err, data) {
|
||||
lambda_arn = data;
|
||||
return cb(err, data);
|
||||
});
|
||||
@ -192,55 +194,62 @@ JAWS.prototype.deploy = function(program) {
|
||||
|
||||
lambda.deleteFunction({
|
||||
FunctionName: lambda_config.FunctionName
|
||||
}, function(err, data) {
|
||||
}, function (err, data) {
|
||||
|
||||
if (err) return console.log(err, err.stack); // an error occurred
|
||||
if (err) {
|
||||
return deferred.reject(err);
|
||||
}
|
||||
|
||||
console.log('****** JAWS: Re-uploading your Lambda Function to AWS Lambda with these parameters: ');
|
||||
console.log(params);
|
||||
|
||||
lambda.createFunction(params, function(err, data) {
|
||||
lambda.createFunction(params, function (err, data) {
|
||||
return cb(err, data);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}, function(err, results) {
|
||||
}, function (err, results) {
|
||||
|
||||
if (err) return console.log(err);
|
||||
if (err) {
|
||||
return deferred.reject(err);
|
||||
}
|
||||
|
||||
// Return
|
||||
console.log('****** JAWS: Success! - Your Lambda Function has been successfully deployed to AWS Lambda. This Lambda Function\'s ARNs are: ');
|
||||
for (i = 0; i < results.length; i++) console.log(results[i].FunctionArn);
|
||||
return;
|
||||
var functionArns = [];
|
||||
for (var i in results) {
|
||||
functionArns.push(results[i].FunctionArn);
|
||||
}
|
||||
|
||||
deferred.resolve(functionArns);
|
||||
});
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
|
||||
JAWS.prototype._zipfileTmpPath = function(program) {
|
||||
JAWS.prototype._zipfileTmpPath = function (functionName) {
|
||||
var ms_since_epoch = +new Date;
|
||||
var filename = program.functionName + '-' + ms_since_epoch + '.zip';
|
||||
var zipfile = path.join(os.tmpDir(), filename);
|
||||
var filename = functionName + '-' + ms_since_epoch + '.zip';
|
||||
var zipfile = path.join(os.tmpDir(), filename);
|
||||
|
||||
return zipfile;
|
||||
};
|
||||
|
||||
|
||||
JAWS.prototype._zip = function(program, codeDirectory, callback) {
|
||||
var zipfile = this._zipfileTmpPath(program);
|
||||
JAWS.prototype._zip = function (functionName, codeDirectory, callback) {
|
||||
var zipfile = this._zipfileTmpPath(functionName);
|
||||
|
||||
var options = {
|
||||
type: 'nodebuffer',
|
||||
compression: 'DEFLATE'
|
||||
}
|
||||
};
|
||||
|
||||
var files = wrench.readdirSyncRecursive(codeDirectory);
|
||||
files.forEach(function(file) {
|
||||
files.forEach(function (file) {
|
||||
var filePath = [codeDirectory, file].join('/');
|
||||
var isFile = fs.lstatSync(filePath).isFile();
|
||||
var isFile = fs.lstatSync(filePath).isFile();
|
||||
if (isFile) {
|
||||
var content = fs.readFileSync(filePath);
|
||||
zip.file(file, content);
|
||||
@ -253,17 +262,16 @@ JAWS.prototype._zip = function(program, codeDirectory, callback) {
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* JAWS: Start "site" Server
|
||||
*/
|
||||
|
||||
JAWS.prototype.server = function(program) {
|
||||
JAWS.prototype.server = function () {
|
||||
|
||||
// Check if in server root folder
|
||||
if (!fs.existsSync(process.cwd() + '/server.js')) return console.log('****** JAWS: Error - You must be in the "site" directory of your JAWS application to run this command and start the server.');
|
||||
|
||||
var child = exec('node server', function(error, stdout, stderr) {
|
||||
var child = exec('node server', function (error, stdout, stderr) {
|
||||
if (error !== null) console.log('exec error: ' + error);
|
||||
});
|
||||
|
||||
@ -272,7 +280,5 @@ JAWS.prototype.server = function(program) {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Export
|
||||
module.exports = new JAWS();
|
||||
110
cli/package.json
110
cli/package.json
@ -1,55 +1,57 @@
|
||||
{
|
||||
"name": "jaws-cli",
|
||||
"version": "0.0.1",
|
||||
"description": "Command line interface for the JAWS stack",
|
||||
"main": "lib/main.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha test/*.js"
|
||||
},
|
||||
"bin": {
|
||||
"jaws": "./bin/jaws"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/servant-app/JAWS.git"
|
||||
},
|
||||
"keywords": [
|
||||
"jaws",
|
||||
"jaws stack",
|
||||
"api gateway",
|
||||
"lambda",
|
||||
"aws",
|
||||
"amazon",
|
||||
"amazon-lambda",
|
||||
"aws-lambda"
|
||||
],
|
||||
"readmeFilename": "README.md",
|
||||
"author": "ac360",
|
||||
"license": "BSD",
|
||||
"devDependencies": {
|
||||
"adm-zip": "^0.4.7",
|
||||
"chai": "^2.0.0",
|
||||
"hoek": "^2.11.1",
|
||||
"lodash": "^3.2.0",
|
||||
"mocha": "",
|
||||
"should": ""
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^0.9.0",
|
||||
"aws-sdk": "^2.1.24",
|
||||
"commander": "^2.5.0",
|
||||
"del": "^1.2.0",
|
||||
"dotenv": "^1.2.0",
|
||||
"jsonfile": "^2.2.1",
|
||||
"moment": "^2.10.6",
|
||||
"node-uuid": "^1.4.2",
|
||||
"node-zip": "^1.1.0",
|
||||
"nodemon": "^1.3.8",
|
||||
"rimraf": "^2.2.8",
|
||||
"shortid": "^2.2.2",
|
||||
"wrench": "^1.5.8"
|
||||
}
|
||||
}
|
||||
"name": "jaws-cli",
|
||||
"version": "0.0.1",
|
||||
"description": "Command line interface for the JAWS stack",
|
||||
"main": "lib/main.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha test/*.js"
|
||||
},
|
||||
"bin": {
|
||||
"jaws": "./bin/jaws"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/servant-app/JAWS.git"
|
||||
},
|
||||
"keywords": [
|
||||
"jaws",
|
||||
"jaws stack",
|
||||
"api gateway",
|
||||
"lambda",
|
||||
"aws",
|
||||
"amazon",
|
||||
"amazon-lambda",
|
||||
"aws-lambda"
|
||||
],
|
||||
"readmeFilename": "README.md",
|
||||
"author": "ac360",
|
||||
"license": "BSD",
|
||||
"devDependencies": {
|
||||
"adm-zip": "^0.4.7",
|
||||
"chai": "^2.0.0",
|
||||
"hoek": "^2.11.1",
|
||||
"lodash": "^3.2.0",
|
||||
"mocha": "",
|
||||
"should": ""
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^0.9.0",
|
||||
"aws-sdk": "^2.1.24",
|
||||
"commander": "^2.5.0",
|
||||
"del": "^1.2.0",
|
||||
"dotenv": "^1.2.0",
|
||||
"js-yaml": "^3.3.1",
|
||||
"jsonfile": "^2.2.1",
|
||||
"moment": "^2.10.6",
|
||||
"node-uuid": "^1.4.2",
|
||||
"node-zip": "^1.1.0",
|
||||
"nodemon": "^1.3.8",
|
||||
"q": "^1.4.1",
|
||||
"rimraf": "^2.2.8",
|
||||
"shortid": "^2.2.2",
|
||||
"wrench": "^1.5.8"
|
||||
}
|
||||
}
|
||||
|
||||
3
cli/temp.adminenv
Normal file
3
cli/temp.adminenv
Normal file
@ -0,0 +1,3 @@
|
||||
### IAM Admin with perms to create/update lambdas and deploy
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
13
cli/tests/all.js
Normal file
13
cli/tests/all.js
Normal file
@ -0,0 +1,13 @@
|
||||
describe('AllTests', function () {
|
||||
before(function (done) {
|
||||
this.timeout(0); //dont timeout anything, creating tables, deleting tables etc
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
after(function () {
|
||||
});
|
||||
|
||||
//require('./wsclient/index');
|
||||
require('./controllers/weather');
|
||||
});
|
||||
59
cli/tests/deploy/index.js
Normal file
59
cli/tests/deploy/index.js
Normal file
@ -0,0 +1,59 @@
|
||||
var assert = require("chai").assert,
|
||||
JAWS = require('../../lib/main');
|
||||
|
||||
describe('deploy', function () {
|
||||
before(function (done) {
|
||||
this.timeout(0); //dont timeout anything, creating tables, deleting tables etc
|
||||
done();
|
||||
});
|
||||
|
||||
describe('test env', function (ddone) {
|
||||
this.timeout(0);
|
||||
|
||||
it('successful', function (done) {
|
||||
this.timeout(0);
|
||||
|
||||
JAWS.deploy("test", {});
|
||||
|
||||
////rochester, MN
|
||||
//weather
|
||||
// .closestPlaces(44.0150757, -92.4775256, 30, 50000)
|
||||
// .then(function (locations) {
|
||||
// assert.deepEqual(locations, ['Blooming Prairie, MN',
|
||||
// 'Waltham, MN',
|
||||
// 'Hayfield, MN',
|
||||
// 'Claremont, MN',
|
||||
// 'Dodge Center, MN',
|
||||
// 'West Concord, MN',
|
||||
// 'Kenyon, MN',
|
||||
// 'Sargeant, MN',
|
||||
// 'Racine, MN',
|
||||
// 'Stewartville, MN',
|
||||
// 'Chatfield, MN',
|
||||
// 'Kasson, MN',
|
||||
// 'Mantorville, MN',
|
||||
// 'Byron, MN',
|
||||
// 'Rochester, MN',
|
||||
// 'Zumbrota, MN',
|
||||
// 'Pine Island, MN',
|
||||
// 'Oronoco, MN',
|
||||
// 'Mazeppa, MN',
|
||||
// 'Eyota, MN',
|
||||
// 'Dover, MN',
|
||||
// 'Viola, MN',
|
||||
// 'Elgin, MN',
|
||||
// 'Hammond, MN',
|
||||
// 'Zumbro Falls, MN',
|
||||
// 'Millville, MN',
|
||||
// 'Plainview, MN',
|
||||
// 'Theilman, MN']);
|
||||
// done();
|
||||
// })
|
||||
// .catch(function (err) {
|
||||
// console.error(err);
|
||||
// done(err);
|
||||
// });
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@ -16,9 +16,8 @@ module.exports = {
|
||||
|
||||
// AWS
|
||||
aws: {
|
||||
admin_access_key: process.env.AWS_ADMIN_ACCESS_KEY,
|
||||
admin_secret_access_key: process.env.AWS_ADMIN_SECRET_ACCESS_KEY,
|
||||
aws_region: 'us-east-1'
|
||||
dynamoDbEndpoint: global.process.env.DYNAMODB_LOCAL_ENDPT || '' //"http://localhost:8000" for localdynamodb-local
|
||||
//logger: process.stdout //uncomment if you want aws sdk logging
|
||||
},
|
||||
|
||||
// JSON Web Token
|
||||
|
||||
@ -7,22 +7,18 @@
|
||||
|
||||
// Dependencies
|
||||
var Config = require('../config/config');
|
||||
var AWS = require('aws-sdk');
|
||||
|
||||
|
||||
// Config AWS Client
|
||||
AWS.config.update({
|
||||
accessKeyId: Config.aws.admin_access_key,
|
||||
secretAccessKey: Config.aws.admin_secret_access_key,
|
||||
region: Config.aws.aws_region
|
||||
});
|
||||
var AWS = require('aws-sdk');
|
||||
|
||||
// Creds read from IAM role or
|
||||
if (Config.aws.logger) {
|
||||
AWS.config.update({logger: config.aws.logger});
|
||||
}
|
||||
|
||||
/**
|
||||
* Export AWS Services
|
||||
*/
|
||||
|
||||
module.exports.DynamoDB = function() {
|
||||
module.exports.DynamoDB = function () {
|
||||
var DOC = require('dynamodb-doc');
|
||||
return new DOC.DynamoDB(new AWS.DynamoDB());
|
||||
};
|
||||
|
||||
@ -5,33 +5,33 @@
|
||||
|
||||
|
||||
// Dependencies
|
||||
var Config = require('../config/config');
|
||||
var Utilities = require('../utilities/utilities');
|
||||
var Config = require('../config/config');
|
||||
var Utilities = require('../utilities/utilities');
|
||||
var AppDynamoDB = require('./model_aws').DynamoDB;
|
||||
AppDynamoDB = new AppDynamoDB();
|
||||
AppDynamoDB = new AppDynamoDB();
|
||||
|
||||
var moment = require('moment');
|
||||
var moment = require('moment');
|
||||
var bcryptjs = require('bcryptjs');
|
||||
var _ = require('lodash');
|
||||
var jwt = require('jsonwebtoken');
|
||||
var _ = require('lodash');
|
||||
var jwt = require('jsonwebtoken');
|
||||
|
||||
|
||||
// DynamoDB Table Name for this Model
|
||||
var dynamodb_table = 'jaws_users';
|
||||
var dynamodb_table = process.env.JAWS_DATA_MODEL_PREFIX + '-jaws-users';
|
||||
|
||||
|
||||
// Export
|
||||
module.exports = new User();
|
||||
|
||||
function User() {}
|
||||
|
||||
function User() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* SignUp
|
||||
*/
|
||||
|
||||
User.prototype.signUp = function(data, callback) {
|
||||
User.prototype.signUp = function (data, callback) {
|
||||
|
||||
// Defaults
|
||||
var _this = this;
|
||||
@ -58,7 +58,7 @@ User.prototype.signUp = function(data, callback) {
|
||||
|
||||
|
||||
// Check if email is already in use
|
||||
_this.showByEmail(data.email, function(error, user) {
|
||||
_this.showByEmail(data.email, function (error, user) {
|
||||
|
||||
|
||||
if (error) return callback(error, null);
|
||||
@ -69,7 +69,6 @@ User.prototype.signUp = function(data, callback) {
|
||||
}, null);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Instantiate
|
||||
*/
|
||||
@ -89,19 +88,18 @@ User.prototype.signUp = function(data, callback) {
|
||||
user = _this.hashPassword(user);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Save
|
||||
*/
|
||||
|
||||
_this.save(user, function(error, user) {
|
||||
_this.save(user, function (error, user) {
|
||||
|
||||
|
||||
if (error) return callback(error, null);
|
||||
|
||||
|
||||
/**
|
||||
* Create JSON Web Token & Return
|
||||
* Create JSON Web Token & Return
|
||||
*/
|
||||
|
||||
var token = jwt.sign({
|
||||
@ -119,14 +117,11 @@ User.prototype.signUp = function(data, callback) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SignIn
|
||||
*/
|
||||
|
||||
User.prototype.signIn = function(data, callback) {
|
||||
User.prototype.signIn = function (data, callback) {
|
||||
|
||||
// Defaults
|
||||
var _this = this;
|
||||
@ -147,9 +142,8 @@ User.prototype.signIn = function(data, callback) {
|
||||
}, null);
|
||||
|
||||
|
||||
|
||||
// Check if email is already in use
|
||||
_this.showByEmail(data.email, function(error, user) {
|
||||
_this.showByEmail(data.email, function (error, user) {
|
||||
|
||||
if (error) return callback(error, null);
|
||||
|
||||
@ -166,24 +160,21 @@ User.prototype.signIn = function(data, callback) {
|
||||
}, null);
|
||||
|
||||
|
||||
|
||||
// Update User
|
||||
user.sign_in_count++;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Save
|
||||
*/
|
||||
|
||||
_this.save(user, function(error, user) {
|
||||
_this.save(user, function (error, user) {
|
||||
|
||||
if (error) return (error, null);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create JSON Web Token & Return
|
||||
* Create JSON Web Token & Return
|
||||
*/
|
||||
|
||||
var token = jwt.sign({
|
||||
@ -202,14 +193,11 @@ User.prototype.signIn = function(data, callback) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ShowByEmail
|
||||
*/
|
||||
|
||||
User.prototype.showByEmail = function(email, callback) {
|
||||
User.prototype.showByEmail = function (email, callback) {
|
||||
|
||||
|
||||
/**
|
||||
@ -222,19 +210,18 @@ User.prototype.showByEmail = function(email, callback) {
|
||||
}, null);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find User
|
||||
*/
|
||||
|
||||
var params = {};
|
||||
params.TableName = dynamodb_table;
|
||||
params.IndexName = "email-index";
|
||||
var params = {};
|
||||
params.TableName = dynamodb_table;
|
||||
params.IndexName = "email-index";
|
||||
params.KeyConditions = [
|
||||
AppDynamoDB.Condition("email", "EQ", email)
|
||||
];
|
||||
|
||||
AppDynamoDB.query(params, function(error, response) {
|
||||
AppDynamoDB.query(params, function (error, response) {
|
||||
|
||||
if (error || !response) return callback({
|
||||
status: 500,
|
||||
@ -248,16 +235,11 @@ User.prototype.showByEmail = function(email, callback) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ShowByID
|
||||
*/
|
||||
|
||||
User.prototype.showByID = function(user_id, callback) {
|
||||
User.prototype.showByID = function (user_id, callback) {
|
||||
|
||||
|
||||
/**
|
||||
@ -270,18 +252,17 @@ User.prototype.showByID = function(user_id, callback) {
|
||||
}, null);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find User
|
||||
*/
|
||||
|
||||
var params = {};
|
||||
params.TableName = dynamodb_table;
|
||||
var params = {};
|
||||
params.TableName = dynamodb_table;
|
||||
params.KeyConditions = [
|
||||
AppDynamoDB.Condition("_id", "EQ", user_id)
|
||||
];
|
||||
|
||||
AppDynamoDB.query(params, function(error, response) {
|
||||
AppDynamoDB.query(params, function (error, response) {
|
||||
|
||||
if (error || !response) return callback({
|
||||
status: 500,
|
||||
@ -295,14 +276,12 @@ User.prototype.showByID = function(user_id, callback) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Save
|
||||
* - Updates existing record or creates a record if one does not already exist
|
||||
*/
|
||||
|
||||
User.prototype.save = function(user, callback) {
|
||||
User.prototype.save = function (user, callback) {
|
||||
|
||||
|
||||
/**
|
||||
@ -341,48 +320,47 @@ User.prototype.save = function(user, callback) {
|
||||
* Basic Information
|
||||
*/
|
||||
|
||||
// email
|
||||
params.UpdateExpression = params.UpdateExpression + '#a0 = :email_val, ';
|
||||
params.ExpressionAttributeNames['#a0'] = 'email';
|
||||
// email
|
||||
params.UpdateExpression = params.UpdateExpression + '#a0 = :email_val, ';
|
||||
params.ExpressionAttributeNames['#a0'] = 'email';
|
||||
params.ExpressionAttributeValues[':email_val'] = user.email;
|
||||
|
||||
// password
|
||||
params.UpdateExpression = params.UpdateExpression + '#a1 = :password_val, ';
|
||||
params.ExpressionAttributeNames['#a1'] = 'password';
|
||||
params.UpdateExpression = params.UpdateExpression + '#a1 = :password_val, ';
|
||||
params.ExpressionAttributeNames['#a1'] = 'password';
|
||||
params.ExpressionAttributeValues[':password_val'] = user.password;
|
||||
|
||||
// salt
|
||||
params.UpdateExpression = params.UpdateExpression + '#a2 = :salt_val, ';
|
||||
params.ExpressionAttributeNames['#a2'] = 'salt';
|
||||
params.UpdateExpression = params.UpdateExpression + '#a2 = :salt_val, ';
|
||||
params.ExpressionAttributeNames['#a2'] = 'salt';
|
||||
params.ExpressionAttributeValues[':salt_val'] = user.salt;
|
||||
|
||||
// plan
|
||||
params.UpdateExpression = params.UpdateExpression + '#a3 = :plan_val, ';
|
||||
params.ExpressionAttributeNames['#a3'] = 'plan';
|
||||
params.UpdateExpression = params.UpdateExpression + '#a3 = :plan_val, ';
|
||||
params.ExpressionAttributeNames['#a3'] = 'plan';
|
||||
params.ExpressionAttributeValues[':plan_val'] = user.plan;
|
||||
|
||||
// sign_in_count
|
||||
params.UpdateExpression = params.UpdateExpression + '#a4 = :sign_in_count_val, ';
|
||||
params.ExpressionAttributeNames['#a4'] = 'sign_in_count';
|
||||
params.UpdateExpression = params.UpdateExpression + '#a4 = :sign_in_count_val, ';
|
||||
params.ExpressionAttributeNames['#a4'] = 'sign_in_count';
|
||||
params.ExpressionAttributeValues[':sign_in_count_val'] = user.sign_in_count;
|
||||
|
||||
// updated
|
||||
params.UpdateExpression = params.UpdateExpression + '#b0 = :updated_val, ';
|
||||
params.ExpressionAttributeNames['#b0'] = 'updated';
|
||||
params.UpdateExpression = params.UpdateExpression + '#b0 = :updated_val, ';
|
||||
params.ExpressionAttributeNames['#b0'] = 'updated';
|
||||
params.ExpressionAttributeValues[':updated_val'] = moment().unix();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Save
|
||||
*/
|
||||
|
||||
// Remove Any Trailing Commas & Space In Update Expression
|
||||
// Remove Any Trailing Commas & Space In Update Expression
|
||||
params.UpdateExpression = params.UpdateExpression.trim();
|
||||
if (params.UpdateExpression[params.UpdateExpression.length - 1] === ',') params.UpdateExpression = params.UpdateExpression.substring(0, params.UpdateExpression.length - 1);
|
||||
|
||||
|
||||
AppDynamoDB.updateItem(params, function(error, response) {
|
||||
AppDynamoDB.updateItem(params, function (error, response) {
|
||||
|
||||
if (error || !response) return callback({
|
||||
status: 500,
|
||||
@ -395,15 +373,13 @@ User.prototype.save = function(user, callback) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Hash Password
|
||||
*/
|
||||
|
||||
User.prototype.hashPassword = function(user) {
|
||||
User.prototype.hashPassword = function (user) {
|
||||
|
||||
user.salt = bcryptjs.genSaltSync(10);
|
||||
user.salt = bcryptjs.genSaltSync(10);
|
||||
user.password = bcryptjs.hashSync(user.password, user.salt);
|
||||
|
||||
return user;
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
"test": "test"
|
||||
},
|
||||
"engines": {
|
||||
"node": "0.12.x",
|
||||
"npm": "2.1.x"
|
||||
"node": "0.10.33",
|
||||
"npm": "1.4.28"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^1.2.1",
|
||||
|
||||
15
lib/temp.env
15
lib/temp.env
@ -2,12 +2,13 @@
|
||||
JWT_ISSUER=JAWS
|
||||
JWT_SECRET=JAWSJAWSJAWS123
|
||||
|
||||
#### AWS Variables
|
||||
AWS_ADMIN_ACCESS_KEY=123123
|
||||
AWS_ADMIN_SECRET_ACCESS_KEY=456456
|
||||
AWS_LAMBDA_ROLE_ARN=arn:aws:iam::28933237018:role/jaws_lambda_role
|
||||
AWS_LAMBDA_REGIONS=us-east-1
|
||||
|
||||
|
||||
### AWS SDK Variables. Key/secret are auto populated by IAM Role
|
||||
AWS_REGION=us-east-1
|
||||
|
||||
### JAWS Variables
|
||||
JAWS_DATA_MODEL_PREFIX=test
|
||||
|
||||
### Custom Variables
|
||||
GOOGLE_SERVER_API_KEY=
|
||||
|
||||
|
||||
|
||||
57
package.json
57
package.json
@ -1,30 +1,29 @@
|
||||
{
|
||||
"name": "jaws-stack",
|
||||
"version": "0.0.1",
|
||||
"description": "The Javascript + AWS Web Application Boilerplate",
|
||||
"author": "Austen Collins",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/servant-app/JAWS.git"
|
||||
},
|
||||
"keywords": [
|
||||
"jaws",
|
||||
"api gateway",
|
||||
"lambda",
|
||||
"aws",
|
||||
"boilerplate",
|
||||
"command",
|
||||
"dynamodb",
|
||||
"s3",
|
||||
"template",
|
||||
"framework"
|
||||
],
|
||||
"engines": {
|
||||
"node": "0.12.x",
|
||||
"npm": "2.1.x"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/servant-app/JAWS/issues"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
"name": "jaws-stack",
|
||||
"version": "0.0.1",
|
||||
"description": "The Javascript + AWS Web Application Boilerplate",
|
||||
"author": "Austen Collins",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/servant-app/JAWS.git"
|
||||
},
|
||||
"keywords": [
|
||||
"jaws",
|
||||
"api gateway",
|
||||
"lambda",
|
||||
"aws",
|
||||
"boilerplate",
|
||||
"command",
|
||||
"dynamodb",
|
||||
"s3",
|
||||
"template",
|
||||
"framework"
|
||||
],
|
||||
"engines": {
|
||||
"node": "0.10.33",
|
||||
"npm": "1.4.28"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/servant-app/JAWS/issues"
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user