-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #386 from aws/npm-browserifiable
Allow SDK to be be browserified without custom scripts Closes #383
- Loading branch information
Showing
12 changed files
with
2,494 additions
and
2,629 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,6 @@ configuration | |
configuration.sample | ||
coverage | ||
dist | ||
dist-tools | ||
doc | ||
doc-src | ||
eslint-rules | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,142 +1,89 @@ | ||
#!/usr/bin/env node | ||
|
||
var fs = require('fs'); | ||
var util = require('util'); | ||
var path = require('path'); | ||
|
||
var CacheStrategy = require('./strategies/cache'); | ||
var DefaultStrategy = require('./strategies/default'); | ||
var AWS = require('../'); | ||
|
||
var defaultServices = 'cloudwatch,cognitoidentity,cognitosync,dynamodb,kinesis,elastictranscoder,s3,sqs,sns,sts'; | ||
var sanitizeRegex = /[^a-zA-Z0-9,-]/; | ||
var license = [ | ||
'// AWS SDK for JavaScript v' + AWS.VERSION, | ||
'// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.', | ||
'// License at https://sdk.amazonaws.com/js/BUNDLE_LICENSE.txt' | ||
].join('\n') + '\n'; | ||
|
||
function Builder(options) { | ||
this.setDefaultOptions(options); | ||
this.serviceCode = []; | ||
this.builtServices = {}; | ||
this.buildStrategy = this.options.cache ? | ||
new CacheStrategy(this) : new DefaultStrategy(this); | ||
function minify(code) { | ||
var uglify = require('uglify-js'); | ||
var minified = uglify.minify(code, {fromString: true}); | ||
return minified.code; | ||
} | ||
|
||
Builder.prototype.setDefaultOptions = function(options) { | ||
this.options = options || {}; | ||
this.options.libPath = this.options.libPath || this.getRootPath(); | ||
this.options.cacheRoot = this.options.cacheRoot || | ||
path.join(this.options.libPath, 'dist-tools', 'cache'); | ||
this.options.cache = this.options.cache || false; | ||
this.options.writeCache = this.options.writeCache || false; | ||
this.options.minify = this.options.minify || false; | ||
this.options.minifyOptions = this.options.minifyOptions || {compress: false}; | ||
}; | ||
|
||
Builder.prototype.getRootPath = function() { | ||
return path.join(__dirname, '..'); | ||
}; | ||
|
||
Builder.prototype.cachePath = function(path) { | ||
var fullPath = this.options.cacheRoot; | ||
if (path) { | ||
fullPath += '/' + path + (this.options.minify ? '.min' : '') + '.js'; | ||
} | ||
|
||
return fullPath; | ||
}; | ||
|
||
Builder.prototype.cacheExists = function(path) { | ||
return fs.existsSync(this.cachePath(path)); | ||
}; | ||
|
||
Builder.prototype.buildService = function(name, usingDefaultServices) { | ||
var match = name.match(/^(.+?)(?:-(.+?))?$/); | ||
var service = match[1], version = match[2] || 'latest'; | ||
var contents = []; | ||
var lines, err; | ||
|
||
if (!this.builtServices[service]) { | ||
this.builtServices[service] = {}; | ||
|
||
lines = this.buildStrategy.getServiceHeader(service); | ||
if (lines === null) { | ||
if (!usingDefaultServices) { | ||
err = new Error('Invalid module: ' + service); | ||
err.name = 'InvalidModuleError'; | ||
throw err; | ||
} | ||
} else { | ||
contents.push(lines); | ||
function stripComments(code) { | ||
var lines = code.split(/\r?\n/); | ||
var multiLine = false; | ||
lines = lines.map(function (line) { | ||
var rLine = line; | ||
if (line.match(/^\s*\/\//)) { | ||
rLine = null; | ||
} else if (line.match(/^\s*\/\*/)) { | ||
multiLine = true; | ||
rLine = null; | ||
} | ||
} | ||
|
||
if (!this.builtServices[service][version]) { | ||
this.builtServices[service][version] = true; | ||
|
||
lines = this.buildStrategy.getService(service, version); | ||
if (lines === null) { | ||
if (!usingDefaultServices) { | ||
err = new Error('Invalid module: ' + service + '-' + version); | ||
err.name = 'InvalidModuleError'; | ||
throw err; | ||
if (multiLine) { | ||
var multiLineEnd = line.match(/\*\/(.*)/); | ||
if (multiLineEnd) { | ||
multiLine = false; | ||
rLine = multiLineEnd[1]; | ||
} else { | ||
rLine = null; | ||
} | ||
} else { | ||
contents.push(lines); | ||
} | ||
} | ||
|
||
return contents.join('\n'); | ||
}; | ||
return rLine; | ||
}).filter(function(l) { return l !== null; }); | ||
|
||
Builder.prototype.addServices = function(services) { | ||
var usingDefaultServices = false; | ||
if (!services) { | ||
usingDefaultServices = true; | ||
services = defaultServices; | ||
} | ||
if (services.match(sanitizeRegex)) { | ||
throw new Error('Incorrectly formatted service names'); | ||
var newCode = lines.join('\n'); | ||
newCode = newCode.replace(/\/\*\*[\s\S]+?Copyright\s+.+?Amazon[\s\S]+?\*\//g, ''); | ||
return newCode; | ||
} | ||
|
||
function build(options, callback) { | ||
if (arguments.length === 1) { | ||
callback = options; | ||
options = {}; | ||
} | ||
|
||
var invalidModules = []; | ||
var stsIncluded = false; | ||
services.split(',').sort().forEach(function(name) { | ||
if (name.match(/^sts\b/) || name === 'all') stsIncluded = true; | ||
try { | ||
this.serviceCode.push(this.buildService(name, usingDefaultServices)); | ||
} catch (e) { | ||
if (e.name === 'InvalidModuleError') invalidModules.push(name); | ||
else throw e; | ||
} | ||
}.bind(this)); | ||
var img = require('browserify/node_modules/insert-module-globals'); | ||
img.vars.process = function() { return '{browser:true}'; }; | ||
|
||
if (!stsIncluded) { | ||
this.serviceCode.push(this.buildService('sts')); | ||
} | ||
if (options.services) process.env.AWS_SERVICES = options.services; | ||
|
||
if (invalidModules.length > 0) { | ||
throw new Error('Missing modules: ' + invalidModules.join(', ')); | ||
} | ||
var browserify = require('browserify'); | ||
var brOpts = { basedir: path.resolve(__dirname, '..') }; | ||
browserify(brOpts).add('./').ignore('domain').bundle(function(err, data) { | ||
if (err) return callback(err); | ||
|
||
return this; | ||
}; | ||
var code = (data || '').toString(); | ||
if (options.minify) code = minify(code); | ||
else code = stripComments(code); | ||
|
||
Builder.prototype.build = function(callback) { | ||
this.buildStrategy.getCore(function(err, core) { | ||
callback(err, err ? null : (core + ';' + this.serviceCode.join('\n'))); | ||
}.bind(this)); | ||
code = license + code; | ||
callback(null, code); | ||
}); | ||
}; | ||
|
||
// run if we called this tool directly | ||
if (require.main === module) { | ||
var options = { | ||
minify: process.env.MINIFY ? true : false, | ||
cache: process.env.CACHE ? true : false, | ||
writeCache: process.env.WRITE_CACHE ? true : false, | ||
cacheRoot: process.env.CACHE_ROOT, | ||
libPath: process.env.LIB_PATH | ||
services: process.argv[2] || process.env.SERVICES, | ||
minify: process.env.MINIFY ? true : false | ||
}; | ||
var services = process.argv[2] || process.env.SERVICES; | ||
new Builder(options).addServices(services).build(function (err, code) { | ||
build(options, function(err, code) { | ||
if (err) console.error(err.message); | ||
else console.log(code); | ||
}); | ||
} | ||
|
||
module.exports = Builder; | ||
build.license = license; | ||
module.exports = build; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
var fs = require('fs'); | ||
var util = require('util'); | ||
var path = require('path'); | ||
|
||
var AWS = require('../'); | ||
var apis = require('../lib/api_loader'); | ||
|
||
var defaultServices = 'cloudwatch,cognitoidentity,cognitosync,dynamodb,kinesis,elastictranscoder,s3,sqs,sns,sts'; | ||
var sanitizeRegex = /[^a-zA-Z0-9,-]/; | ||
|
||
var serviceClasses = {}; | ||
Object.keys(AWS).forEach(function(name) { | ||
if (AWS[name].serviceIdentifier) { | ||
serviceClasses[AWS[name].serviceIdentifier] = AWS[name]; | ||
} | ||
}); | ||
|
||
function getServiceHeader(service) { | ||
if (service === 'all') { | ||
return Object.keys(serviceClasses).map(function(service) { | ||
return getServiceHeader(service); | ||
}).join('\n'); | ||
} | ||
|
||
if (!serviceClasses[service]) return null; | ||
var versions = serviceClasses[service].apiVersions.map(function(version) { | ||
return version.indexOf('*') >= 0 ? null : version; | ||
}).filter(function(c) { return c !== null; }); | ||
|
||
var file = util.format( | ||
'AWS.apiLoader.services[\'%s\'] = {};\n' + | ||
'AWS.%s = AWS.Service.defineService(\'%s\', %s);\n', | ||
service, apis.serviceName(service), service, util.inspect(versions)); | ||
var svcPath = path.join(__dirname, '..', 'lib', 'services', service + '.js'); | ||
if (fs.existsSync(svcPath)) { | ||
file += 'require(\'./services/' + service + '\');\n'; | ||
} | ||
|
||
return file; | ||
} | ||
|
||
function getService(service, version) { | ||
if (service === 'all') { | ||
return Object.keys(serviceClasses).map(function(service) { | ||
var out = serviceClasses[service].apiVersions.map(function(version) { | ||
if (version.indexOf('*') >= 0) return null; | ||
return getService(service, version); | ||
}).filter(function(c) { return c !== null; }).join('\n'); | ||
|
||
return out; | ||
}).join('\n'); | ||
} | ||
|
||
var svc, api; | ||
if (!serviceClasses[service]) { | ||
return null; | ||
} | ||
|
||
try { | ||
var ClassName = serviceClasses[service]; | ||
svc = new ClassName({apiVersion: version, endpoint: 'localhost'}); | ||
api = apis.load(service, svc.api.apiVersion); | ||
} catch (e) { | ||
return null; | ||
} | ||
|
||
var line = util.format( | ||
'AWS.apiLoader.services[\'%s\'][\'%s\'] = %s;', | ||
service, svc.api.apiVersion, JSON.stringify(api)); | ||
|
||
return line; | ||
} | ||
|
||
function ServiceCollector(services) { | ||
var builtServices = {}; | ||
|
||
function buildService(name, usingDefaultServices) { | ||
var match = name.match(/^(.+?)(?:-(.+?))?$/); | ||
var service = match[1], version = match[2] || 'latest'; | ||
var contents = []; | ||
var lines, err; | ||
|
||
if (!builtServices[service]) { | ||
builtServices[service] = {}; | ||
|
||
lines = getServiceHeader(service); | ||
if (lines === null) { | ||
if (!usingDefaultServices) { | ||
err = new Error('Invalid module: ' + service); | ||
err.name = 'InvalidModuleError'; | ||
throw err; | ||
} | ||
} else { | ||
contents.push(lines); | ||
} | ||
} | ||
|
||
if (!builtServices[service][version]) { | ||
builtServices[service][version] = true; | ||
|
||
lines = getService(service, version); | ||
if (lines === null) { | ||
if (!usingDefaultServices) { | ||
err = new Error('Invalid module: ' + service + '-' + version); | ||
err.name = 'InvalidModuleError'; | ||
throw err; | ||
} | ||
} else { | ||
contents.push(lines); | ||
} | ||
} | ||
|
||
return contents.join('\n'); | ||
} | ||
|
||
var serviceCode = ''; | ||
var usingDefaultServices = false; | ||
if (!services) { | ||
usingDefaultServices = true; | ||
services = defaultServices; | ||
} | ||
if (services.match(sanitizeRegex)) { | ||
throw new Error('Incorrectly formatted service names'); | ||
} | ||
|
||
var invalidModules = []; | ||
var stsIncluded = false; | ||
services.split(',').sort().forEach(function(name) { | ||
if (name.match(/^sts\b/) || name === 'all') stsIncluded = true; | ||
try { | ||
serviceCode += buildService(name, usingDefaultServices) + '\n'; | ||
} catch (e) { | ||
if (e.name === 'InvalidModuleError') invalidModules.push(name); | ||
else throw e; | ||
} | ||
}); | ||
|
||
if (!stsIncluded) { | ||
serviceCode += buildService('sts') + '\n'; | ||
} | ||
|
||
if (invalidModules.length > 0) { | ||
throw new Error('Missing modules: ' + invalidModules.join(', ')); | ||
} | ||
|
||
return serviceCode; | ||
} | ||
|
||
module.exports = ServiceCollector; |
Oops, something went wrong.