├── .npmignore ├── testProjects ├── default │ ├── handlers │ │ ├── differentName.js │ │ ├── syntaxError.js │ │ ├── noModule.js │ │ ├── excluded.js │ │ ├── simple.js │ │ ├── es5.js │ │ ├── es5Named.js │ │ ├── multiple.dots.in.name.js │ │ ├── hasLib.js │ │ └── multiple.js │ ├── package.json │ ├── index.test.js │ ├── serverless.yml │ ├── __snapshots__ │ │ └── index.test.js.snap │ └── yarn.lock ├── localInvoke │ ├── handlers │ │ └── simple.js │ ├── serverless.yml │ ├── package.json │ └── yarn.lock ├── cosmi │ ├── handlers │ │ └── simple.js │ ├── serverless.yml │ ├── index.test.js │ ├── package.json │ ├── __snapshots__ │ │ └── index.test.js.snap │ └── yarn.lock ├── metaPackage │ ├── handlers │ │ └── simple.js │ ├── package.json │ ├── serverless.yml │ └── yarn.lock ├── offline │ ├── handlers │ │ └── index.js │ ├── serverless.yml │ ├── package.json │ └── test.js └── util │ └── unzipRun.js ├── .babelrc ├── example ├── index.js ├── serverless.yml ├── package.json └── yarn.lock ├── src ├── util │ ├── hrMillis.js │ └── track.js ├── handlerCode.js ├── __snapshots__ │ └── index.test.js.snap ├── index.test.js ├── index.js └── __mocks__ │ └── sls.js ├── .gitignore ├── circle.yml ├── webpack.config.js ├── .circleci └── config.yml ├── .github └── ISSUE_TEMPLATE.md ├── util └── testProjects.js ├── package.json ├── readme.md └── LICENSE /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | spec/* 3 | *.test.js 4 | __mocks__ 5 | __snapshots__ 6 | jest 7 | coverage 8 | testProject 9 | -------------------------------------------------------------------------------- /testProjects/default/handlers/differentName.js: -------------------------------------------------------------------------------- 1 | module.exports.wow = (event, context) => { 2 | context.succeed(301); 3 | }; 4 | -------------------------------------------------------------------------------- /testProjects/default/handlers/syntaxError.js: -------------------------------------------------------------------------------- 1 | const uuid = require('uuid'); 2 | 3 | module.exports.handler = (event, context) => { 4 | const foo = { 5 | context.succeed(response); 6 | }; 7 | -------------------------------------------------------------------------------- /testProjects/localInvoke/handlers/simple.js: -------------------------------------------------------------------------------- 1 | module.exports.handler = (event, context) => { 2 | if (!context.iopipe) { 3 | throw new Error('No iopipe'); 4 | } 5 | context.succeed('Success'); 6 | }; 7 | -------------------------------------------------------------------------------- /testProjects/cosmi/handlers/simple.js: -------------------------------------------------------------------------------- 1 | module.exports.handler = (event, context) => { 2 | if (!context.iopipe || !context.iopipe.mark) { 3 | return context.succeed(new Error('No plugins')); 4 | } 5 | return context.succeed(200); 6 | }; 7 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "./node_modules/@iopipe/scripts/dist/config/babelrc.js", 4 | ["env", { 5 | "targets": { 6 | "node": ["4.3"] 7 | }, 8 | "exclude": ["transform-regenerator"] 9 | }] 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | module.exports.handler = (event, context) => { 2 | const response = { 3 | statusCode: 200, 4 | body: JSON.stringify({ 5 | message: 'Hi from Lambda!', 6 | input: event 7 | }) 8 | }; 9 | context.succeed(response); 10 | }; 11 | -------------------------------------------------------------------------------- /src/util/hrMillis.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | 3 | export default function(startTime = process.hrtime(), suffix = true) { 4 | const endTime = process.hrtime(startTime); 5 | const millis = _.round(endTime[0] * 1000 + endTime[1] / 1000000); 6 | return suffix ? `${millis}ms` : millis; 7 | } 8 | -------------------------------------------------------------------------------- /testProjects/default/handlers/noModule.js: -------------------------------------------------------------------------------- 1 | exports.handler = (event, context, callback) => { 2 | const response = { 3 | statusCode: 200, 4 | body: JSON.stringify({ 5 | message: 'Go Serverless v1.0! Your function executed successfully!', 6 | input: event 7 | }) 8 | }; 9 | callback(null, response); 10 | }; 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.sublime-project 3 | *.sublime-workspace 4 | *.log 5 | .serverless 6 | v8-compile-cache-* 7 | jest/* 8 | coverage 9 | dist 10 | .serverless_plugins 11 | testProjects/*/package-lock.json 12 | testProjects/*/yarn.lock 13 | iopipe-handlers.js 14 | *-iopipe.js 15 | .iopipe 16 | iopipe_handlers 17 | .serverlessUnzipped 18 | -------------------------------------------------------------------------------- /example/serverless.yml: -------------------------------------------------------------------------------- 1 | service: example 2 | provider: 3 | name: aws 4 | runtime: nodejs6.10 5 | stage: prod 6 | region: us-west-2 7 | plugins: 8 | - serverless-plugin-iopipe 9 | environment: 10 | IOPIPE_TOKEN: ${env:IOPIPE_TOKEN} 11 | functions: 12 | hello: 13 | handler: index.handler 14 | custom: 15 | iopipeNoVerify: true 16 | -------------------------------------------------------------------------------- /testProjects/default/handlers/excluded.js: -------------------------------------------------------------------------------- 1 | module.exports.handler = (event, context, callback) => { 2 | const response = { 3 | statusCode: 200, 4 | body: JSON.stringify({ 5 | message: 'Go Serverless v1.0! Your function executed successfully!', 6 | input: event 7 | }) 8 | }; 9 | callback(null, response); 10 | }; 11 | -------------------------------------------------------------------------------- /testProjects/default/handlers/simple.js: -------------------------------------------------------------------------------- 1 | const uuid = require('uuid'); 2 | 3 | module.exports.handler = (event, context) => { 4 | const response = { 5 | statusCode: 200, 6 | body: JSON.stringify({ 7 | message: `Your uuid is: ${uuid.v4()}`, 8 | input: event 9 | }) 10 | }; 11 | context.succeed(response); 12 | }; 13 | -------------------------------------------------------------------------------- /testProjects/localInvoke/serverless.yml: -------------------------------------------------------------------------------- 1 | service: sls-iopipe 2 | provider: 3 | name: aws 4 | runtime: nodejs6.10 5 | stage: prod 6 | region: us-west-2 7 | environment: 8 | IOPIPE_TOKEN: ${env:IOPIPE_TOKEN} 9 | plugins: 10 | - serverless-plugin-iopipe/index.js 11 | functions: 12 | simple: 13 | handler: handlers/simple.handler 14 | -------------------------------------------------------------------------------- /testProjects/default/handlers/es5.js: -------------------------------------------------------------------------------- 1 | module.exports.handler = function handler(event, context, callback) { 2 | const response = { 3 | statusCode: 200, 4 | body: JSON.stringify({ 5 | message: 'Go Serverless v1.0! Your function executed successfully!', 6 | input: event 7 | }) 8 | }; 9 | callback(null, response); 10 | }; 11 | -------------------------------------------------------------------------------- /testProjects/metaPackage/handlers/simple.js: -------------------------------------------------------------------------------- 1 | const uuid = require('uuid'); 2 | 3 | module.exports.handler = (event, context) => { 4 | const response = { 5 | statusCode: 200, 6 | body: JSON.stringify({ 7 | message: `Your uuid is: ${uuid.v4()}`, 8 | input: event 9 | }) 10 | }; 11 | context.succeed(response); 12 | }; 13 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | override: 3 | - yarn 4 | cache_directories: 5 | - ~/.cache/yarn 6 | machine: 7 | node: 8 | version: 8.10.0 9 | test: 10 | override: 11 | - yarn 12 | - yarn run validate 13 | deployment: 14 | release: 15 | branch: master 16 | owner: iopipe 17 | commands: 18 | - yarn run release 19 | -------------------------------------------------------------------------------- /testProjects/default/handlers/es5Named.js: -------------------------------------------------------------------------------- 1 | module.exports.handler = function handler(event, context, callback) { 2 | const response = { 3 | statusCode: 200, 4 | body: JSON.stringify({ 5 | message: 'Go Serverless v1.0! Your function executed successfully!', 6 | input: event 7 | }) 8 | }; 9 | callback(null, response); 10 | }; 11 | -------------------------------------------------------------------------------- /testProjects/default/handlers/multiple.dots.in.name.js: -------------------------------------------------------------------------------- 1 | module.exports.handler = (event, context, callback) => { 2 | const response = { 3 | statusCode: 200, 4 | body: JSON.stringify({ 5 | message: 'Go Serverless v1.0! Your function executed successfully!', 6 | input: event 7 | }) 8 | }; 9 | callback(null, response); 10 | }; 11 | -------------------------------------------------------------------------------- /testProjects/default/handlers/hasLib.js: -------------------------------------------------------------------------------- 1 | const iopipe = require('iopipe')({ clientId: 'FOOBAR' }); 2 | 3 | module.exports.handler = iopipe((event, context, callback) => { 4 | const response = { 5 | statusCode: 200, 6 | body: JSON.stringify({ 7 | message: 'Go Serverless v1.0! Your function executed successfully!', 8 | input: event 9 | }) 10 | }; 11 | callback(null, response); 12 | }); 13 | -------------------------------------------------------------------------------- /testProjects/offline/handlers/index.js: -------------------------------------------------------------------------------- 1 | exports.handler = (event, context) => { 2 | let body = { success: true }; 3 | const params = event.queryStringParameters || {}; 4 | const { fail } = params; 5 | if (!context.iopipe || fail) { 6 | body = { err: 'No iopipe object found on context' }; 7 | } 8 | return context.succeed({ 9 | statusCode: 200, 10 | body: JSON.stringify(body) 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /testProjects/cosmi/serverless.yml: -------------------------------------------------------------------------------- 1 | service: sls-test 2 | provider: 3 | name: aws 4 | runtime: nodejs6.10 5 | stage: prod 6 | region: us-west-2 7 | plugins: 8 | - serverless-plugin-iopipe/index.js 9 | environment: 10 | IOPIPE_TOKEN: ${env:IOPIPE_TOKEN} 11 | iamRoleStatements: 12 | - Effect: "Allow" 13 | Action: 14 | - "logs:*" 15 | Resource: 16 | - "*" 17 | functions: 18 | simple: 19 | handler: handlers/simple.handler 20 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "iopipe": "^1.1.0" 14 | }, 15 | "devDependencies": { 16 | "serverless": "^1.23.0", 17 | "serverless-plugin-iopipe": "^0.3.3" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /testProjects/localInvoke/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sls-unit-test-local-invoke", 3 | "version": "0.0.0-test", 4 | "description": "", 5 | "main": "handler.js", 6 | "dependencies": { 7 | "@iopipe/iopipe": "1.8.0" 8 | }, 9 | "scripts": { 10 | "build": "echo 'No need to build'", 11 | "invoke": "SLS_DEBUG=* IOPIPE_TOKEN=test_token node ../../node_modules/serverless/bin/serverless invoke local -f simple", 12 | "test": "npm run invoke" 13 | }, 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": {} 17 | } -------------------------------------------------------------------------------- /testProjects/default/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sls-unit-test-default", 3 | "version": "0.0.0-test", 4 | "description": "", 5 | "main": "handler.js", 6 | "dependencies": { 7 | "iopipe": "^1.5.0", 8 | "uuid": "^3.0.1" 9 | }, 10 | "scripts": { 11 | "build": "SLS_DEBUG=* IOPIPE_TOKEN='test-token' node ../../node_modules/serverless/bin/serverless package", 12 | "test": "node ../../node_modules/jest/bin/jest.js", 13 | "validate": "npm run build && npm run jest" 14 | }, 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": {} 18 | } 19 | -------------------------------------------------------------------------------- /testProjects/metaPackage/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sls-unit-test-meta", 3 | "version": "0.0.0-test", 4 | "description": "", 5 | "main": "handler.js", 6 | "dependencies": { 7 | "@iopipe/iopipe": "1.8.0", 8 | "uuid": "^3.0.1" 9 | }, 10 | "scripts": { 11 | "build": "SLS_DEBUG=* IOPIPE_TOKEN='test-token' node ../../node_modules/serverless/bin/serverless package", 12 | "test": "node ../../node_modules/jest/bin/jest.js", 13 | "validate": "npm run build && npm run test" 14 | }, 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": {} 18 | } -------------------------------------------------------------------------------- /testProjects/offline/serverless.yml: -------------------------------------------------------------------------------- 1 | service: sls-iopipe-offline-test 2 | provider: 3 | name: aws 4 | runtime: nodejs6.10 5 | stage: prod 6 | region: us-west-2 7 | environment: 8 | IOPIPE_TOKEN: ${env:IOPIPE_TOKEN} 9 | plugins: 10 | - serverless-plugin-iopipe/index.js 11 | - serverless-offline 12 | functions: 13 | index: 14 | handler: handlers/index.handler 15 | events: 16 | - http: 17 | path: / 18 | method: get 19 | custom: 20 | serverless-offline: 21 | port: 4982 22 | host: 127.0.0.1 23 | iopipeHandlerDir: iopipe_handlers 24 | -------------------------------------------------------------------------------- /testProjects/cosmi/index.test.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable import/no-extraneous-dependencies*/ 2 | import _ from 'lodash'; 3 | 4 | import { cleanup, run, unzip } from '../util/unzipRun'; 5 | 6 | process.env.IOPIPE_TOKEN = 'test_token'; 7 | 8 | const dir = __dirname; 9 | 10 | beforeAll(() => { 11 | unzip({ dir }); 12 | }); 13 | 14 | afterAll(() => { 15 | cleanup({ dir }); 16 | }); 17 | 18 | test('Generated files requires plugin and includes plugin inline', async () => { 19 | const simpleRes = await run({ 20 | dir, 21 | file: 'simple-iopipe.js' 22 | }); 23 | expect(simpleRes).toBe(200); 24 | }); 25 | -------------------------------------------------------------------------------- /testProjects/offline/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sls-unit-test-local-invoke", 3 | "version": "0.0.0-test", 4 | "description": "", 5 | "main": "handler.js", 6 | "dependencies": { 7 | "@iopipe/iopipe": "^1.5.0", 8 | "cross-spawn": "^6.0.5", 9 | "got": "^8.3.0", 10 | "serverless-offline": "^3.20.2" 11 | }, 12 | "scripts": { 13 | "build": "echo 'No need to build'", 14 | "start": "SLS_DEBUG=* IOPIPE_TOKEN=test_token node ../../node_modules/serverless/bin/serverless offline start", 15 | "test": "IOPIPE_TOKEN=test_token node test" 16 | }, 17 | "author": "", 18 | "license": "ISC", 19 | "devDependencies": {} 20 | } 21 | -------------------------------------------------------------------------------- /testProjects/metaPackage/serverless.yml: -------------------------------------------------------------------------------- 1 | service: sls-iopipe 2 | provider: 3 | name: aws 4 | runtime: nodejs6.10 5 | stage: prod 6 | region: us-west-2 7 | plugins: 8 | - serverless-plugin-iopipe/index.js 9 | environment: 10 | NODE_ENV: ${env:NODE_ENV} 11 | IOPIPE_TOKEN: ${env:IOPIPE_TOKEN} 12 | custom: 13 | iopipeQuote: double 14 | iopipeExclude: excluded,foo 15 | iopipePlaceholder: false 16 | extraCustomKey: true 17 | iopipeTestInterpolate: ${env:NODE_ENV} 18 | iamRoleStatements: 19 | - Effect: "Allow" 20 | Action: 21 | - "logs:*" 22 | Resource: 23 | - "*" 24 | functions: 25 | simple: 26 | handler: handlers/simple.handler 27 | -------------------------------------------------------------------------------- /src/handlerCode.js: -------------------------------------------------------------------------------- 1 | let handler, handlerError; 2 | // The following is an automatically generated require statement by the plugin, 3 | // aimed to provide syntax/type errors to the IOpipe service. 4 | // The original file is imported as text with capitalized tokens replaced. 5 | try { 6 | handler = require('../RELATIVE_PATH'); 7 | } catch (err) { 8 | handlerError = err; 9 | } 10 | 11 | exports['EXPORT_NAME'] = function FUNCTION_NAME(event, context, callback) { 12 | try { 13 | return iopipe((evt, ctx, cb) => { 14 | if (handlerError) { 15 | return cb(handlerError); 16 | } 17 | return handler.METHOD(evt, ctx, cb); 18 | })(event, context, callback); 19 | } catch (err) { 20 | throw err; 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const nodeExternals = require('webpack-node-externals'); 3 | 4 | module.exports = { 5 | target: 'node', 6 | entry: './src/index.js', 7 | output: { 8 | path: path.resolve(__dirname, 'dist'), 9 | filename: './index.js', 10 | libraryTarget: 'commonjs2', 11 | library: 'iopipe-serverless-plugin' 12 | }, 13 | externals: [ 14 | nodeExternals({ 15 | whitelist: [/babel-runtime/, /regenerator-runtime/, /core-js/] 16 | }) 17 | ], 18 | module: { 19 | rules: [ 20 | { 21 | test: /\.js$/, 22 | exclude: /(node_modules)/, 23 | use: { 24 | loader: 'babel-loader' 25 | } 26 | }, 27 | { 28 | test: /handlerCode/, 29 | use: 'raw-loader' 30 | } 31 | ] 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /testProjects/cosmi/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sls-unit-test-cosmi", 3 | "version": "0.0.0-test", 4 | "description": "", 5 | "main": "handler.js", 6 | "dependencies": { 7 | "@iopipe/core": "1.13.0", 8 | "@iopipe/event-info": "^0.1.1", 9 | "@iopipe/logger": "^1.0.0", 10 | "@iopipe/trace": "^0.3.0" 11 | }, 12 | "scripts": { 13 | "build": "SLS_DEBUG=* IOPIPE_TOKEN='test-token' node ../../node_modules/serverless/bin/serverless package", 14 | "test": "node ../../node_modules/jest/bin/jest.js", 15 | "validate": "npm run build && npm run jest" 16 | }, 17 | "author": "", 18 | "license": "ISC", 19 | "devDependencies": {}, 20 | "iopipe": { 21 | "plugins": [ 22 | "@iopipe/event-info", 23 | "@iopipe/trace", 24 | [ 25 | "@iopipe/logger", 26 | { 27 | "enabled": true 28 | } 29 | ] 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /testProjects/default/index.test.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable import/no-extraneous-dependencies*/ 2 | import _ from 'lodash'; 3 | 4 | import { cleanup, run, unzip } from '../util/unzipRun'; 5 | 6 | process.env.IOPIPE_TOKEN = 'test_token'; 7 | 8 | const dir = __dirname; 9 | 10 | beforeAll(() => { 11 | unzip({ dir }); 12 | }); 13 | 14 | afterAll(() => { 15 | cleanup({ dir }); 16 | }); 17 | 18 | test('Generated files require plugin, include plugin inline, and export original handler', async () => { 19 | const simpleRes = await run({ 20 | dir, 21 | file: 'simple-iopipe.js' 22 | }); 23 | expect(simpleRes.statusCode).toBe(200); 24 | 25 | const nameMismatchRes = await run({ 26 | dir, 27 | file: 'nameMismatch-iopipe.js' 28 | }); 29 | expect(nameMismatchRes).toBe(301); 30 | 31 | const syntaxErrorRes = await run({ 32 | dir, 33 | file: 'syntaxError-iopipe.js' 34 | }); 35 | expect(syntaxErrorRes.message).toMatch(/Unexpected\stoken,\s/); 36 | }); 37 | -------------------------------------------------------------------------------- /testProjects/default/handlers/multiple.js: -------------------------------------------------------------------------------- 1 | module.exports.doNotHandle = (event, context, callback) => { 2 | const response = { 3 | statusCode: 200, 4 | body: JSON.stringify({ 5 | message: 'Go Serverless v1.0! Your function executed successfully!', 6 | input: event 7 | }) 8 | }; 9 | callback(null, response); 10 | }; 11 | 12 | module.exports.handler = (event, context, callback) => { 13 | const response = { 14 | statusCode: 200, 15 | body: JSON.stringify({ 16 | message: 'Go Serverless v1.0! Your function executed successfully!', 17 | input: event 18 | }) 19 | }; 20 | callback(null, response); 21 | }; 22 | 23 | module.exports.differentNameHandler = (event, context, callback) => { 24 | const response = { 25 | statusCode: 200, 26 | body: JSON.stringify({ 27 | message: 'Go Serverless v1.0! Your function executed successfully!', 28 | input: event 29 | }) 30 | }; 31 | callback(null, response); 32 | }; 33 | -------------------------------------------------------------------------------- /testProjects/offline/test.js: -------------------------------------------------------------------------------- 1 | const gotLib = require('got'); 2 | const spawn = require('cross-spawn'); 3 | 4 | const got = str => gotLib(str, { json: true }); 5 | const BASE = `http://127.0.0.1:4982`; 6 | 7 | async function run() { 8 | // make sure that the error state works too 9 | const { body: { err } } = await got(`${BASE}?fail=true`); 10 | if (err !== 'No iopipe object found on context') { 11 | throw new Error(err || 'Wrong'); 12 | } 13 | const { body: { success } } = await got(BASE); 14 | if (success !== true) { 15 | throw new Error('No success msg'); 16 | } 17 | return true; 18 | } 19 | 20 | const offlineChild = spawn('npm', ['start'], { 21 | stdio: 'inherit', 22 | // http://azimi.me/2014/12/31/kill-child_process-node-js.html 23 | detached: true 24 | }); 25 | 26 | setTimeout(async () => { 27 | let err; 28 | try { 29 | await run(); 30 | } catch (e) { 31 | err = e; 32 | } 33 | process.kill(-offlineChild.pid, 'SIGINT'); 34 | if (err) { 35 | throw err; 36 | } 37 | }, process.env.OFFLINE_STARTUP_MILLIS || 5000); 38 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | defaults: &defaults 2 | docker: 3 | - image: iopipe/circleci 4 | working_directory: ~/circleci-deployment 5 | 6 | version: 2 7 | 8 | jobs: 9 | test: 10 | <<: *defaults 11 | steps: 12 | - checkout 13 | - restore_cache: 14 | key: yarn-cache-{{ .Branch }}-{{ checksum "yarn.lock" }} 15 | - run: yarn 16 | - run: yarn run validate 17 | - save_cache: 18 | key: v1-dist-{{ .Environment.CIRCLE_BRANCH }}-{{ .Environment.CIRCLE_SHA1 }} 19 | paths: 20 | - dist 21 | 22 | release: 23 | <<: *defaults 24 | steps: 25 | - checkout 26 | - restore_cache: 27 | key: yarn-cache-{{ .Branch }}-{{ checksum "yarn.lock" }} 28 | - restore_cache: 29 | key: v1-dist-{{ .Environment.CIRCLE_BRANCH }}-{{ .Environment.CIRCLE_SHA1 }} 30 | - run: yarn 31 | - run: yarn run release 32 | 33 | workflows: 34 | version: 2 35 | all: 36 | jobs: 37 | - test 38 | - release: 39 | requires: 40 | - test 41 | filters: 42 | branches: 43 | only: master 44 | -------------------------------------------------------------------------------- /testProjects/cosmi/__snapshots__/index.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Generated files requires plugin and includes plugin inline 1`] = ` 4 | "const iopipe = require('@iopipe/core')({\\"plugins\\":[require('@iopipe/event-info')(),require('@iopipe/trace')(),require('@iopipe/logger')({\\"enabled\\":true})],\\"token\\":\\"test-token\\",\\"installMethod\\":\\"serverless-plugin-iopipe@0.0.0-semantically-released\\"}); 5 | 6 | let handler, handlerError; 7 | // The following is an automatically generated require statement by the plugin, 8 | // aimed to provide syntax/type errors to the IOpipe service. 9 | // The original file is imported as text with capitalized tokens replaced. 10 | try { 11 | handler = require('../handlers/simple'); 12 | } catch (err) { 13 | handlerError = err; 14 | } 15 | 16 | exports['simple'] = function attemptSimple(event, context, callback) { 17 | try { 18 | return iopipe((evt, ctx, cb) => { 19 | if (handlerError) { 20 | return cb(handlerError); 21 | } 22 | return handler.handler(evt, ctx, cb); 23 | })(event, context, callback); 24 | } catch (err) { 25 | throw err; 26 | } 27 | }; 28 | " 29 | `; 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 13 | 14 | **Description** 15 | 16 | 19 | 20 | **Steps to reproduce the issue:** 21 | 1. 22 | 2. 23 | 3. 24 | 25 | **Describe the results you received:** 26 | 27 | 28 | **Describe the results you expected:** 29 | 30 | **Application and library versions** 31 | 38 | 39 | **Additional information you deem important (e.g. issue happens only occasionally):** 40 | -------------------------------------------------------------------------------- /testProjects/default/serverless.yml: -------------------------------------------------------------------------------- 1 | service: sls-test 2 | provider: 3 | name: aws 4 | runtime: nodejs6.10 5 | stage: prod 6 | region: us-west-2 7 | plugins: 8 | - serverless-plugin-iopipe/index.js 9 | environment: 10 | NODE_ENV: ${env:NODE_ENV} 11 | IOPIPE_TOKEN: ${env:IOPIPE_TOKEN} 12 | custom: 13 | iopipeQuote: double 14 | iopipeExclude: excluded,foo 15 | iopipePlaceholder: false 16 | extraCustomKey: true 17 | iopipeTestInterpolate: ${env:NODE_ENV} 18 | iamRoleStatements: 19 | - Effect: "Allow" 20 | Action: 21 | - "logs:*" 22 | Resource: 23 | - "*" 24 | functions: 25 | simple: 26 | handler: handlers/simple.handler 27 | multiple: 28 | handler: handlers/multiple.handler 29 | multipleDifferentHandler: 30 | handler: handlers/multiple.differentNameHandler 31 | es5: 32 | handler: handlers/es5.handler 33 | multiple-dots-in-name: 34 | handler: handlers/multiple.dots.in.name.handler 35 | noModule: 36 | handler: handlers/noModule.handler 37 | excluded: 38 | handler: handlers/excluded.handler 39 | syntaxError: 40 | handler: handlers/syntaxError.handler 41 | es5Named: 42 | handler: handlers/es5Named.handler 43 | python: 44 | handler: python/main.longRunning 45 | runtime: python2.7 46 | nameMismatch: 47 | handler: handlers/differentName.wow 48 | -------------------------------------------------------------------------------- /src/__snapshots__/index.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Agent instantiation only includes installMethod if no iopipeToken in custom section of serverless.yml 1`] = `"const iopipe = require('iopipe')({\\"installMethod\\":\\"serverless-plugin-iopipe@0.0.0-semantically-released\\",\\"plugins\\":[]});"`; 4 | 5 | exports[`Can create iopipe handler file 1`] = ` 6 | "const iopipe = require('iopipe')({\\"token\\":\\"TEST_TOKEN\\",\\"installMethod\\":\\"serverless-plugin-iopipe@0.0.0-semantically-released\\",\\"plugins\\":[]}); 7 | 8 | let handler, handlerError; 9 | // The following is an automatically generated require statement by the plugin, 10 | // aimed to provide syntax/type errors to the IOpipe service. 11 | // The original file is imported as text with capitalized tokens replaced. 12 | try { 13 | handler = require('../handlers/simple'); 14 | } catch (err) { 15 | handlerError = err; 16 | } 17 | 18 | exports['simple'] = function attemptSimple(event, context, callback) { 19 | try { 20 | return iopipe((evt, ctx, cb) => { 21 | if (handlerError) { 22 | return cb(handlerError); 23 | } 24 | return handler.handler(evt, ctx, cb); 25 | })(event, context, callback); 26 | } catch (err) { 27 | throw err; 28 | } 29 | }; 30 | " 31 | `; 32 | 33 | exports[`Warns if iopipe token is not found 1`] = `"You did not specify iopipeToken in your custom section of serverless.yml. iopipe will fall back to $IOPIPE_TOKEN in the lambda environment"`; 34 | -------------------------------------------------------------------------------- /testProjects/util/unzipRun.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable import/no-extraneous-dependencies*/ 2 | /*eslint-disable import/no-dynamic-require*/ 3 | import path from 'path'; 4 | import fs from 'fs-extra'; 5 | import _ from 'lodash'; 6 | import AdmZip from 'adm-zip'; 7 | 8 | function getFilePathAndContents({ dir = __dirname, file = '' }) { 9 | const filePath = path.join( 10 | dir, 11 | '.serverlessUnzipped', 12 | 'iopipe_handlers', 13 | file 14 | ); 15 | const contents = fs.readFileSync(filePath, 'utf8'); 16 | return { path: filePath, contents }; 17 | } 18 | 19 | function cleanup({ dir = __dirname }) { 20 | const unzippedFolderPath = path.join(dir, '.serverlessUnzipped'); 21 | fs.removeSync(unzippedFolderPath); 22 | } 23 | 24 | function unzip({ dir = __dirname, serviceName = 'sls-test' }) { 25 | const zip = new AdmZip(path.join(dir, `./.serverless/${serviceName}.zip`)); 26 | const unzippedFolderPath = path.join(dir, '.serverlessUnzipped'); 27 | // clear out any previous unzipped dir 28 | cleanup({ dir }); 29 | zip.extractAllTo(unzippedFolderPath, true); 30 | } 31 | 32 | function run({ dir = __dirname, file = '', method: rawMethod }) { 33 | const method = rawMethod || _.head(file.split('-')); 34 | const { path: filePath, contents } = getFilePathAndContents({ dir, file }); 35 | expect(contents).toMatchSnapshot(); 36 | 37 | const mod = require(filePath); 38 | return new Promise(succeed => { 39 | mod[method]({}, { succeed }, succeed); 40 | }); 41 | } 42 | 43 | export { cleanup, run, unzip }; 44 | -------------------------------------------------------------------------------- /src/util/track.js: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import { createHash } from 'crypto'; 3 | import ua from 'universal-analytics'; 4 | import fs from 'fs-extra'; 5 | import _ from 'lodash'; 6 | import uuid from 'uuid'; 7 | import debugLib from 'debug'; 8 | 9 | const debug = debugLib('serverless-plugin-iopipe:track'); 10 | 11 | export function getVisitor(pluginInstance) { 12 | // create consistent, yet anonymized id for usage stats 13 | let pkg = {}; 14 | if (!pluginInstance.getOptions().noStats) { 15 | try { 16 | pkg = fs.readJsonSync(join(pluginInstance.prefix, 'package.json')); 17 | } catch (err) { 18 | _.noop(); 19 | } 20 | } 21 | const str = 22 | pkg.author || 23 | _.get(pkg, 'repository.url') || 24 | pkg.name || 25 | pkg.homepage || 26 | uuid.v4(); 27 | const userId = createHash('md5') 28 | .update(str) 29 | .digest('hex'); 30 | const visitor = ua('UA-73165042-2', userId, { 31 | strictCidFormat: false, 32 | https: true 33 | }); 34 | return visitor; 35 | } 36 | 37 | export function track(pluginInstance, obj = {}) { 38 | const { visitor } = pluginInstance; 39 | if (!visitor) { 40 | return Promise.resolve('no-visitor'); 41 | } 42 | if (pluginInstance.getOptions().noStats) { 43 | return Promise.resolve('no-stats'); 44 | } 45 | const { category = 'event', action = 'action', label = 'label', value } = obj; 46 | const newLabel = _.isString(label) ? label : JSON.stringify(label); 47 | debug(`Tracking ${category}: ${action}`); 48 | return new Promise((resolve, reject) => { 49 | visitor.event(category, action, newLabel, value, (err, res) => { 50 | return err ? reject(err) : resolve(res); 51 | }); 52 | }); 53 | } 54 | -------------------------------------------------------------------------------- /util/testProjects.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable no-console*/ 2 | /*eslint-disable no-process-exit*/ 3 | const path = require('path'); 4 | const fs = require('fs-extra'); 5 | const _ = require('lodash'); 6 | const spawn = require('cross-spawn'); 7 | const argv = require('yargs').argv; 8 | 9 | const testDirFiles = fs.readdirSync(path.join(__dirname, '../testProjects')); 10 | const folders = _.chain(testDirFiles) 11 | .reject(s => s.match(/^\./)) 12 | .reject(s => s === 'util') 13 | .filter(file => { 14 | const toInclude = argv.folders || argv.projects; 15 | if (toInclude) { 16 | return _.includes(toInclude, file); 17 | } 18 | return true; 19 | }) 20 | .value(); 21 | 22 | const results = _.flatten( 23 | folders.map(folder => { 24 | console.log(`Running tests for ${folder}...`); 25 | return _.compact([ 26 | !argv.noInstall && 27 | spawn.sync('yarn', ['install', '--cwd', `testProjects/${folder}`], { 28 | stdio: 'inherit' 29 | }), 30 | 31 | fs.copySync( 32 | 'dist/index.js', 33 | `testProjects/${folder}/.serverless_plugins/serverless-plugin-iopipe/index.js` 34 | ), 35 | 36 | !argv.noBuild && 37 | spawn.sync('yarn', ['--cwd', `testProjects/${folder}`, 'build'], { 38 | stdio: 'inherit' 39 | }), 40 | 41 | spawn.sync( 42 | 'yarn', 43 | _.compact([ 44 | '--cwd', 45 | `testProjects/${folder}`, 46 | 'test', 47 | (argv.u || argv.updateSnapshot) && '--updateSnapshot' 48 | ]), 49 | { 50 | stdio: 'inherit' 51 | } 52 | ), 53 | console.log(`Finished tests for ${folder}.`) 54 | ]); 55 | }) 56 | ); 57 | 58 | process.exit(_.max(_.map(results, 'status')) || 0); 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "IOpipe ", 3 | "bugs": { 4 | "url": "https://github.com/iopipe/serverless-plugin-iopipe/issues" 5 | }, 6 | "dependencies": { 7 | "cosmiconfig": "^3", 8 | "debug": "^2.6.8", 9 | "del": "^3.0.0", 10 | "fs-extra": "^5.0.0", 11 | "lodash": "^4.17.4", 12 | "universal-analytics": "^0.4.13", 13 | "uuid": "^3.0.1" 14 | }, 15 | "description": "Serverless Plugin IOpipe", 16 | "devDependencies": { 17 | "@iopipe/scripts": "^1.4.1", 18 | "adm-zip": "^0.4.7", 19 | "babel-loader": "^7.0.0", 20 | "circular-json": "^0.3.1", 21 | "cross-spawn": "^6.0.4", 22 | "pre-commit": "^1.2.2", 23 | "raw-loader": "^0.5.1", 24 | "serverless": "1.23.0", 25 | "uglify-es": "^3.0.27", 26 | "webpack": "^2.6.1", 27 | "webpack-node-externals": "^1.6.0", 28 | "yargs": "^11.0.0" 29 | }, 30 | "engines": { 31 | "node": ">=4.2.6" 32 | }, 33 | "files": [ 34 | "dist/" 35 | ], 36 | "homepage": "https://github.com/iopipe/serverless-plugin-iopipe#readme", 37 | "jest": { 38 | "testPathIgnorePatterns": [ 39 | "node_modules/", 40 | "dist/", 41 | "testProjects/" 42 | ] 43 | }, 44 | "keywords": [ 45 | "lambda", 46 | "serverless", 47 | "sls", 48 | "agent", 49 | "analytics", 50 | "metrics", 51 | "telemetry", 52 | "tracing", 53 | "distributed tracing", 54 | "jscodeshift", 55 | "codemod" 56 | ], 57 | "license": "Apache-2.0", 58 | "main": "dist/index.js", 59 | "name": "serverless-plugin-iopipe", 60 | "pre-commit": [ 61 | "lint" 62 | ], 63 | "repository": { 64 | "type": "git", 65 | "url": "git+https://github.com/iopipe/serverless-plugin-iopipe.git" 66 | }, 67 | "scripts": { 68 | "build": "NODE_ENV=production npm run folder && npm run webpack && npm run uglify", 69 | "commit": "iopipe-scripts commit", 70 | "folder": "rm -rf dist && mkdir dist", 71 | "lint": "iopipe-scripts lint", 72 | "prepublish": "npm run build", 73 | "release": "iopipe-scripts release", 74 | "sls": "LOCAL_PLUGIN=true SLS_DEBUG=* cd testProject && yarn && npm run build && cd ../", 75 | "slsDeploy": "LOCAL_PLUGIN=true SLS_DEBUG=* cd testProject && yarn && npm run deploy && cd ../", 76 | "test": "iopipe-scripts test", 77 | "testProjects": "node util/testProjects", 78 | "uglify": "./node_modules/uglify-es/bin/uglifyjs dist/index.js --output dist/index.js --beautify", 79 | "validate": "npm run lint && npm run build && npm run test && npm run testProjects", 80 | "webpack": "webpack" 81 | }, 82 | "version": "0.0.0-semantically-released", 83 | "eslintConfig": { 84 | "extends": "./node_modules/@iopipe/scripts/eslint.js" 85 | }, 86 | "eslintIgnore": [ 87 | "coverage", 88 | "node_modules", 89 | "dist", 90 | "handlerCode.js", 91 | ".serverless", 92 | "testProjects/*/node_modules", 93 | "testProjects/*/.serverless", 94 | "testProjects/*/.serverless_plugins", 95 | "syntaxError.js", 96 | "*iopipe.js" 97 | ] 98 | } 99 | -------------------------------------------------------------------------------- /testProjects/default/__snapshots__/index.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Generated files require plugin, include plugin inline, and export original handler 1`] = ` 4 | "const iopipe = require('iopipe')({\\"token\\":\\"test-token\\",\\"installMethod\\":\\"serverless-plugin-iopipe@0.0.0-semantically-released\\",\\"plugins\\":[]}); 5 | 6 | let handler, handlerError; 7 | // The following is an automatically generated require statement by the plugin, 8 | // aimed to provide syntax/type errors to the IOpipe service. 9 | // The original file is imported as text with capitalized tokens replaced. 10 | try { 11 | handler = require('../handlers/simple'); 12 | } catch (err) { 13 | handlerError = err; 14 | } 15 | 16 | exports['simple'] = function attemptSimple(event, context, callback) { 17 | try { 18 | return iopipe((evt, ctx, cb) => { 19 | if (handlerError) { 20 | return cb(handlerError); 21 | } 22 | return handler.handler(evt, ctx, cb); 23 | })(event, context, callback); 24 | } catch (err) { 25 | throw err; 26 | } 27 | }; 28 | " 29 | `; 30 | 31 | exports[`Generated files require plugin, include plugin inline, and export original handler 2`] = ` 32 | "const iopipe = require('iopipe')({\\"token\\":\\"test-token\\",\\"installMethod\\":\\"serverless-plugin-iopipe@0.0.0-semantically-released\\",\\"plugins\\":[]}); 33 | 34 | let handler, handlerError; 35 | // The following is an automatically generated require statement by the plugin, 36 | // aimed to provide syntax/type errors to the IOpipe service. 37 | // The original file is imported as text with capitalized tokens replaced. 38 | try { 39 | handler = require('../handlers/differentName'); 40 | } catch (err) { 41 | handlerError = err; 42 | } 43 | 44 | exports['nameMismatch'] = function attemptNameMismatch(event, context, callback) { 45 | try { 46 | return iopipe((evt, ctx, cb) => { 47 | if (handlerError) { 48 | return cb(handlerError); 49 | } 50 | return handler.wow(evt, ctx, cb); 51 | })(event, context, callback); 52 | } catch (err) { 53 | throw err; 54 | } 55 | }; 56 | " 57 | `; 58 | 59 | exports[`Generated files require plugin, include plugin inline, and export original handler 3`] = ` 60 | "const iopipe = require('iopipe')({\\"token\\":\\"test-token\\",\\"installMethod\\":\\"serverless-plugin-iopipe@0.0.0-semantically-released\\",\\"plugins\\":[]}); 61 | 62 | let handler, handlerError; 63 | // The following is an automatically generated require statement by the plugin, 64 | // aimed to provide syntax/type errors to the IOpipe service. 65 | // The original file is imported as text with capitalized tokens replaced. 66 | try { 67 | handler = require('../handlers/syntaxError'); 68 | } catch (err) { 69 | handlerError = err; 70 | } 71 | 72 | exports['syntaxError'] = function attemptSyntaxError(event, context, callback) { 73 | try { 74 | return iopipe((evt, ctx, cb) => { 75 | if (handlerError) { 76 | return cb(handlerError); 77 | } 78 | return handler.handler(evt, ctx, cb); 79 | })(event, context, callback); 80 | } catch (err) { 81 | throw err; 82 | } 83 | }; 84 | " 85 | `; 86 | -------------------------------------------------------------------------------- /testProjects/default/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@iopipe/config@^1.0.0": 6 | version "1.0.0" 7 | resolved "https://registry.yarnpkg.com/@iopipe/config/-/config-1.0.0.tgz#25d18d1e7f922225bd5c5dda85d0a08b89811927" 8 | dependencies: 9 | "@iopipe/event-info" "^0.1.0" 10 | "@iopipe/trace" "^0.3.0" 11 | 12 | "@iopipe/core@^1.6.0": 13 | version "1.8.0" 14 | resolved "https://registry.yarnpkg.com/@iopipe/core/-/core-1.8.0.tgz#8b06c4949297b66f31cc699aa078ef9bb407c57b" 15 | dependencies: 16 | cosmiconfig "^4" 17 | lodash.uniqby "^4.7.0" 18 | 19 | "@iopipe/event-info@^0.1.0": 20 | version "0.1.1" 21 | resolved "https://registry.yarnpkg.com/@iopipe/event-info/-/event-info-0.1.1.tgz#cbd435e7151075f4227c66902cef10e36b67a101" 22 | dependencies: 23 | lodash.get "^4.4.2" 24 | 25 | "@iopipe/trace@^0.3.0": 26 | version "0.3.0" 27 | resolved "https://registry.yarnpkg.com/@iopipe/trace/-/trace-0.3.0.tgz#42a558da9c7d310d15f09fddb490fbb7ebbbf399" 28 | dependencies: 29 | iopipe "^1.0.0" 30 | performance-node "^0.2.0" 31 | 32 | argparse@^1.0.7: 33 | version "1.0.10" 34 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 35 | dependencies: 36 | sprintf-js "~1.0.2" 37 | 38 | cosmiconfig@^4: 39 | version "4.0.0" 40 | resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" 41 | dependencies: 42 | is-directory "^0.3.1" 43 | js-yaml "^3.9.0" 44 | parse-json "^4.0.0" 45 | require-from-string "^2.0.1" 46 | 47 | error-ex@^1.3.1: 48 | version "1.3.1" 49 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" 50 | dependencies: 51 | is-arrayish "^0.2.1" 52 | 53 | esprima@^4.0.0: 54 | version "4.0.0" 55 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" 56 | 57 | iopipe@^1.0.0, iopipe@^1.5.0: 58 | version "1.6.0" 59 | resolved "https://registry.yarnpkg.com/iopipe/-/iopipe-1.6.0.tgz#094526617f66a7a3bc8620356e47ffccb2362055" 60 | dependencies: 61 | "@iopipe/config" "^1.0.0" 62 | "@iopipe/core" "^1.6.0" 63 | 64 | is-arrayish@^0.2.1: 65 | version "0.2.1" 66 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 67 | 68 | is-directory@^0.3.1: 69 | version "0.3.1" 70 | resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" 71 | 72 | js-yaml@^3.9.0: 73 | version "3.11.0" 74 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" 75 | dependencies: 76 | argparse "^1.0.7" 77 | esprima "^4.0.0" 78 | 79 | json-parse-better-errors@^1.0.1: 80 | version "1.0.1" 81 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" 82 | 83 | lodash.get@^4.4.2: 84 | version "4.4.2" 85 | resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" 86 | 87 | lodash.uniqby@^4.7.0: 88 | version "4.7.0" 89 | resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" 90 | 91 | parse-json@^4.0.0: 92 | version "4.0.0" 93 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" 94 | dependencies: 95 | error-ex "^1.3.1" 96 | json-parse-better-errors "^1.0.1" 97 | 98 | performance-node@^0.2.0: 99 | version "0.2.0" 100 | resolved "https://registry.yarnpkg.com/performance-node/-/performance-node-0.2.0.tgz#03abf74ac0c455f333be505165dacab9110ef5b3" 101 | 102 | require-from-string@^2.0.1: 103 | version "2.0.1" 104 | resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.1.tgz#c545233e9d7da6616e9d59adfb39fc9f588676ff" 105 | 106 | sprintf-js@~1.0.2: 107 | version "1.0.3" 108 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 109 | 110 | uuid@^3.0.1: 111 | version "3.2.1" 112 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" 113 | -------------------------------------------------------------------------------- /testProjects/localInvoke/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@iopipe/config@^1.2.0": 6 | version "1.2.0" 7 | resolved "https://registry.yarnpkg.com/@iopipe/config/-/config-1.2.0.tgz#264bc0b591d90b24b609d0f20965dd96012f2d9e" 8 | dependencies: 9 | "@iopipe/event-info" "^1.2.1" 10 | "@iopipe/trace" "^1.1.1" 11 | 12 | "@iopipe/core@^1.10.0": 13 | version "1.13.0" 14 | resolved "https://registry.yarnpkg.com/@iopipe/core/-/core-1.13.0.tgz#0fbbace7a58497af1fbda68eb1ab97f1f988ddb3" 15 | dependencies: 16 | cosmiconfig "^4" 17 | lodash.uniqby "^4.7.0" 18 | simple-get "^3.0.2" 19 | 20 | "@iopipe/event-info@^1.2.1": 21 | version "1.2.1" 22 | resolved "https://registry.yarnpkg.com/@iopipe/event-info/-/event-info-1.2.1.tgz#d964446c120aee93a8780650446ed290ce2fff58" 23 | dependencies: 24 | flat "^4.0.0" 25 | lodash.get "^4.4.2" 26 | 27 | "@iopipe/iopipe@1.8.0": 28 | version "1.8.0" 29 | resolved "https://registry.yarnpkg.com/@iopipe/iopipe/-/iopipe-1.8.0.tgz#a9ba81152a513d6f109da948ca306a2bede2ceee" 30 | dependencies: 31 | "@iopipe/config" "^1.2.0" 32 | "@iopipe/core" "^1.10.0" 33 | 34 | "@iopipe/trace@^1.1.1": 35 | version "1.1.1" 36 | resolved "https://registry.yarnpkg.com/@iopipe/trace/-/trace-1.1.1.tgz#05b0f1f85c7695975d2c426d52fb495a0a3678ac" 37 | dependencies: 38 | performance-node "^0.2.0" 39 | 40 | argparse@^1.0.7: 41 | version "1.0.10" 42 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 43 | dependencies: 44 | sprintf-js "~1.0.2" 45 | 46 | cosmiconfig@^4: 47 | version "4.0.0" 48 | resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" 49 | dependencies: 50 | is-directory "^0.3.1" 51 | js-yaml "^3.9.0" 52 | parse-json "^4.0.0" 53 | require-from-string "^2.0.1" 54 | 55 | decompress-response@^3.3.0: 56 | version "3.3.0" 57 | resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" 58 | dependencies: 59 | mimic-response "^1.0.0" 60 | 61 | error-ex@^1.3.1: 62 | version "1.3.1" 63 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" 64 | dependencies: 65 | is-arrayish "^0.2.1" 66 | 67 | esprima@^4.0.0: 68 | version "4.0.0" 69 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" 70 | 71 | flat@^4.0.0: 72 | version "4.1.0" 73 | resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" 74 | dependencies: 75 | is-buffer "~2.0.3" 76 | 77 | is-arrayish@^0.2.1: 78 | version "0.2.1" 79 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 80 | 81 | is-buffer@~2.0.3: 82 | version "2.0.3" 83 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" 84 | 85 | is-directory@^0.3.1: 86 | version "0.3.1" 87 | resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" 88 | 89 | js-yaml@^3.9.0: 90 | version "3.11.0" 91 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" 92 | dependencies: 93 | argparse "^1.0.7" 94 | esprima "^4.0.0" 95 | 96 | json-parse-better-errors@^1.0.1: 97 | version "1.0.1" 98 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" 99 | 100 | lodash.get@^4.4.2: 101 | version "4.4.2" 102 | resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" 103 | 104 | lodash.uniqby@^4.7.0: 105 | version "4.7.0" 106 | resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" 107 | 108 | mimic-response@^1.0.0: 109 | version "1.0.1" 110 | resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" 111 | 112 | once@^1.3.1: 113 | version "1.4.0" 114 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 115 | dependencies: 116 | wrappy "1" 117 | 118 | parse-json@^4.0.0: 119 | version "4.0.0" 120 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" 121 | dependencies: 122 | error-ex "^1.3.1" 123 | json-parse-better-errors "^1.0.1" 124 | 125 | performance-node@^0.2.0: 126 | version "0.2.0" 127 | resolved "https://registry.yarnpkg.com/performance-node/-/performance-node-0.2.0.tgz#03abf74ac0c455f333be505165dacab9110ef5b3" 128 | 129 | require-from-string@^2.0.1: 130 | version "2.0.1" 131 | resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.1.tgz#c545233e9d7da6616e9d59adfb39fc9f588676ff" 132 | 133 | simple-concat@^1.0.0: 134 | version "1.0.0" 135 | resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" 136 | 137 | simple-get@^3.0.2: 138 | version "3.0.2" 139 | resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.0.2.tgz#4646e0d6e1b7d429b914d9642b01e1dfaa5c56e5" 140 | dependencies: 141 | decompress-response "^3.3.0" 142 | once "^1.3.1" 143 | simple-concat "^1.0.0" 144 | 145 | sprintf-js@~1.0.2: 146 | version "1.0.3" 147 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 148 | 149 | wrappy@1: 150 | version "1.0.2" 151 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 152 | -------------------------------------------------------------------------------- /testProjects/metaPackage/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@iopipe/config@^1.2.0": 6 | version "1.2.0" 7 | resolved "https://registry.yarnpkg.com/@iopipe/config/-/config-1.2.0.tgz#264bc0b591d90b24b609d0f20965dd96012f2d9e" 8 | dependencies: 9 | "@iopipe/event-info" "^1.2.1" 10 | "@iopipe/trace" "^1.1.1" 11 | 12 | "@iopipe/core@^1.10.0": 13 | version "1.13.0" 14 | resolved "https://registry.yarnpkg.com/@iopipe/core/-/core-1.13.0.tgz#0fbbace7a58497af1fbda68eb1ab97f1f988ddb3" 15 | dependencies: 16 | cosmiconfig "^4" 17 | lodash.uniqby "^4.7.0" 18 | simple-get "^3.0.2" 19 | 20 | "@iopipe/event-info@^1.2.1": 21 | version "1.2.1" 22 | resolved "https://registry.yarnpkg.com/@iopipe/event-info/-/event-info-1.2.1.tgz#d964446c120aee93a8780650446ed290ce2fff58" 23 | dependencies: 24 | flat "^4.0.0" 25 | lodash.get "^4.4.2" 26 | 27 | "@iopipe/iopipe@1.8.0": 28 | version "1.8.0" 29 | resolved "https://registry.yarnpkg.com/@iopipe/iopipe/-/iopipe-1.8.0.tgz#a9ba81152a513d6f109da948ca306a2bede2ceee" 30 | dependencies: 31 | "@iopipe/config" "^1.2.0" 32 | "@iopipe/core" "^1.10.0" 33 | 34 | "@iopipe/trace@^1.1.1": 35 | version "1.1.1" 36 | resolved "https://registry.yarnpkg.com/@iopipe/trace/-/trace-1.1.1.tgz#05b0f1f85c7695975d2c426d52fb495a0a3678ac" 37 | dependencies: 38 | performance-node "^0.2.0" 39 | 40 | argparse@^1.0.7: 41 | version "1.0.10" 42 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 43 | dependencies: 44 | sprintf-js "~1.0.2" 45 | 46 | cosmiconfig@^4: 47 | version "4.0.0" 48 | resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" 49 | dependencies: 50 | is-directory "^0.3.1" 51 | js-yaml "^3.9.0" 52 | parse-json "^4.0.0" 53 | require-from-string "^2.0.1" 54 | 55 | decompress-response@^3.3.0: 56 | version "3.3.0" 57 | resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" 58 | dependencies: 59 | mimic-response "^1.0.0" 60 | 61 | error-ex@^1.3.1: 62 | version "1.3.1" 63 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" 64 | dependencies: 65 | is-arrayish "^0.2.1" 66 | 67 | esprima@^4.0.0: 68 | version "4.0.0" 69 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" 70 | 71 | flat@^4.0.0: 72 | version "4.1.0" 73 | resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" 74 | dependencies: 75 | is-buffer "~2.0.3" 76 | 77 | is-arrayish@^0.2.1: 78 | version "0.2.1" 79 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 80 | 81 | is-buffer@~2.0.3: 82 | version "2.0.3" 83 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" 84 | 85 | is-directory@^0.3.1: 86 | version "0.3.1" 87 | resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" 88 | 89 | js-yaml@^3.9.0: 90 | version "3.11.0" 91 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" 92 | dependencies: 93 | argparse "^1.0.7" 94 | esprima "^4.0.0" 95 | 96 | json-parse-better-errors@^1.0.1: 97 | version "1.0.1" 98 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" 99 | 100 | lodash.get@^4.4.2: 101 | version "4.4.2" 102 | resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" 103 | 104 | lodash.uniqby@^4.7.0: 105 | version "4.7.0" 106 | resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" 107 | 108 | mimic-response@^1.0.0: 109 | version "1.0.1" 110 | resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" 111 | 112 | once@^1.3.1: 113 | version "1.4.0" 114 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 115 | dependencies: 116 | wrappy "1" 117 | 118 | parse-json@^4.0.0: 119 | version "4.0.0" 120 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" 121 | dependencies: 122 | error-ex "^1.3.1" 123 | json-parse-better-errors "^1.0.1" 124 | 125 | performance-node@^0.2.0: 126 | version "0.2.0" 127 | resolved "https://registry.yarnpkg.com/performance-node/-/performance-node-0.2.0.tgz#03abf74ac0c455f333be505165dacab9110ef5b3" 128 | 129 | require-from-string@^2.0.1: 130 | version "2.0.1" 131 | resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.1.tgz#c545233e9d7da6616e9d59adfb39fc9f588676ff" 132 | 133 | simple-concat@^1.0.0: 134 | version "1.0.0" 135 | resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" 136 | 137 | simple-get@^3.0.2: 138 | version "3.0.2" 139 | resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.0.2.tgz#4646e0d6e1b7d429b914d9642b01e1dfaa5c56e5" 140 | dependencies: 141 | decompress-response "^3.3.0" 142 | once "^1.3.1" 143 | simple-concat "^1.0.0" 144 | 145 | sprintf-js@~1.0.2: 146 | version "1.0.3" 147 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 148 | 149 | uuid@^3.0.1: 150 | version "3.2.1" 151 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" 152 | 153 | wrappy@1: 154 | version "1.0.2" 155 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 156 | -------------------------------------------------------------------------------- /testProjects/cosmi/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@iopipe/config@^1.0.0": 6 | version "1.0.0" 7 | resolved "https://registry.yarnpkg.com/@iopipe/config/-/config-1.0.0.tgz#25d18d1e7f922225bd5c5dda85d0a08b89811927" 8 | dependencies: 9 | "@iopipe/event-info" "^0.1.0" 10 | "@iopipe/trace" "^0.3.0" 11 | 12 | "@iopipe/core@1.13.0", "@iopipe/core@^1.13": 13 | version "1.13.0" 14 | resolved "https://registry.yarnpkg.com/@iopipe/core/-/core-1.13.0.tgz#0fbbace7a58497af1fbda68eb1ab97f1f988ddb3" 15 | dependencies: 16 | cosmiconfig "^4" 17 | lodash.uniqby "^4.7.0" 18 | simple-get "^3.0.2" 19 | 20 | "@iopipe/core@^1.6.0": 21 | version "1.8.0" 22 | resolved "https://registry.yarnpkg.com/@iopipe/core/-/core-1.8.0.tgz#8b06c4949297b66f31cc699aa078ef9bb407c57b" 23 | dependencies: 24 | cosmiconfig "^4" 25 | lodash.uniqby "^4.7.0" 26 | 27 | "@iopipe/event-info@^0.1.0", "@iopipe/event-info@^0.1.1": 28 | version "0.1.1" 29 | resolved "https://registry.yarnpkg.com/@iopipe/event-info/-/event-info-0.1.1.tgz#cbd435e7151075f4227c66902cef10e36b67a101" 30 | dependencies: 31 | lodash.get "^4.4.2" 32 | 33 | "@iopipe/logger@^1.0.0": 34 | version "1.0.0" 35 | resolved "https://registry.yarnpkg.com/@iopipe/logger/-/logger-1.0.0.tgz#079ef734d555dbf8fe15f334be956db24f61a4d4" 36 | dependencies: 37 | "@iopipe/core" "^1.13" 38 | simple-get "^3.0.2" 39 | 40 | "@iopipe/trace@^0.3.0": 41 | version "0.3.0" 42 | resolved "https://registry.yarnpkg.com/@iopipe/trace/-/trace-0.3.0.tgz#42a558da9c7d310d15f09fddb490fbb7ebbbf399" 43 | dependencies: 44 | iopipe "^1.0.0" 45 | performance-node "^0.2.0" 46 | 47 | argparse@^1.0.7: 48 | version "1.0.10" 49 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 50 | dependencies: 51 | sprintf-js "~1.0.2" 52 | 53 | cosmiconfig@^4: 54 | version "4.0.0" 55 | resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" 56 | dependencies: 57 | is-directory "^0.3.1" 58 | js-yaml "^3.9.0" 59 | parse-json "^4.0.0" 60 | require-from-string "^2.0.1" 61 | 62 | decompress-response@^3.3.0: 63 | version "3.3.0" 64 | resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" 65 | dependencies: 66 | mimic-response "^1.0.0" 67 | 68 | error-ex@^1.3.1: 69 | version "1.3.1" 70 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" 71 | dependencies: 72 | is-arrayish "^0.2.1" 73 | 74 | esprima@^4.0.0: 75 | version "4.0.0" 76 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" 77 | 78 | iopipe@^1.0.0: 79 | version "1.6.0" 80 | resolved "https://registry.yarnpkg.com/iopipe/-/iopipe-1.6.0.tgz#094526617f66a7a3bc8620356e47ffccb2362055" 81 | dependencies: 82 | "@iopipe/config" "^1.0.0" 83 | "@iopipe/core" "^1.6.0" 84 | 85 | is-arrayish@^0.2.1: 86 | version "0.2.1" 87 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 88 | 89 | is-directory@^0.3.1: 90 | version "0.3.1" 91 | resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" 92 | 93 | js-yaml@^3.9.0: 94 | version "3.11.0" 95 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" 96 | dependencies: 97 | argparse "^1.0.7" 98 | esprima "^4.0.0" 99 | 100 | json-parse-better-errors@^1.0.1: 101 | version "1.0.1" 102 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" 103 | 104 | lodash.get@^4.4.2: 105 | version "4.4.2" 106 | resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" 107 | 108 | lodash.uniqby@^4.7.0: 109 | version "4.7.0" 110 | resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302" 111 | 112 | mimic-response@^1.0.0: 113 | version "1.0.1" 114 | resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" 115 | 116 | once@^1.3.1: 117 | version "1.4.0" 118 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 119 | dependencies: 120 | wrappy "1" 121 | 122 | parse-json@^4.0.0: 123 | version "4.0.0" 124 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" 125 | dependencies: 126 | error-ex "^1.3.1" 127 | json-parse-better-errors "^1.0.1" 128 | 129 | performance-node@^0.2.0: 130 | version "0.2.0" 131 | resolved "https://registry.yarnpkg.com/performance-node/-/performance-node-0.2.0.tgz#03abf74ac0c455f333be505165dacab9110ef5b3" 132 | 133 | require-from-string@^2.0.1: 134 | version "2.0.1" 135 | resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.1.tgz#c545233e9d7da6616e9d59adfb39fc9f588676ff" 136 | 137 | simple-concat@^1.0.0: 138 | version "1.0.0" 139 | resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" 140 | 141 | simple-get@^3.0.2: 142 | version "3.0.2" 143 | resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.0.2.tgz#4646e0d6e1b7d429b914d9642b01e1dfaa5c56e5" 144 | dependencies: 145 | decompress-response "^3.3.0" 146 | once "^1.3.1" 147 | simple-concat "^1.0.0" 148 | 149 | sprintf-js@~1.0.2: 150 | version "1.0.3" 151 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 152 | 153 | wrappy@1: 154 | version "1.0.2" 155 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 156 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # IOpipe Serverless Framework Plugin 2 | 3 | [![serverless](http://public.serverless.com/badges/v3.svg)](http://www.serverless.com) 4 | [![CircleCI](https://circleci.com/gh/iopipe/serverless-plugin-iopipe/tree/master.svg?style=svg&circle-token=3787c8931aea4de4facb5fde25ae456f294f8cc1)](https://circleci.com/gh/iopipe/serverless-plugin-iopipe/tree/master) 5 | [![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier) 6 | [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) 7 | 8 | A [serverless](http://www.serverless.com) plugin to automatically wrap your functions with [iopipe](https://iopipe.com). 9 | 10 | # Requirements 11 | - Node >= `4.3.2` 12 | - NPM >= `2.14.12` 13 | - Serverless >= `1.13.0` 14 | - Yarn >= `0.22.0` (optional) 15 | - A valid `package.json` file 16 | - A valid `serverless.yml` file 17 | 18 | # Install 19 | With [yarn](https://yarnpkg.com) (recommended) in project directory: 20 | ``` 21 | yarn add @iopipe/iopipe 22 | yarn add serverless-plugin-iopipe --dev 23 | ``` 24 | 25 | OR with npm in project directory: 26 | ``` 27 | npm install @iopipe/iopipe 28 | npm install serverless-plugin-iopipe --save-dev 29 | ``` 30 | 31 | Add the plugin to your `serverless.yml` file: 32 | ```yaml 33 | plugins: 34 | - serverless-plugin-iopipe 35 | ``` 36 | 37 | You'll need to make sure your lambda functions have access to your [IOpipe project token](https://dashboard.iopipe.com/install). The recommended strategy is to use an environment variable. Just setup the variable in serverless.yml like any other. 38 | 39 | ```yaml 40 | environment: 41 | IOPIPE_TOKEN: ${env:IOPIPE_TOKEN} 42 | ``` 43 | 44 | Alternatively, you can add an [iopipe configuration to your package.json](https://github.com/iopipe/iopipe-js-core#packagejson-configuration). 45 | 46 | You're set! The plugin will run during an `sls deploy` or during `sls invoke local`. 47 | 48 | Check out an [example here](https://github.com/iopipe/serverless-plugin-iopipe/blob/master/example/serverless.yml). 49 | 50 | # How Does it Work? 51 | `serverless-plugin-iopipe` outputs files that import and wrap the function handlers defined in `serverless.yml` with IOpipe so you don't have to. It allows you to deploy and upgrade multiple functions simultaneously. 52 | 53 | # Commands 54 | - `sls iopipe clean` This command cleans up your project folder of extraneous `*-iopipe.js` files if needed. This can be useful when using the [serverless-offline](https://github.com/dherault/serverless-offline) plugin. 55 | 56 | # Options 57 | Beyond the required $IOPIPE_TOKEN environment variable, some options can be set [in the "custom" config](https://serverless.com/framework/docs/providers/aws/guide/plugins#installing-plugins) in `serverless.yml`. [See Example](https://github.com/iopipe/serverless-plugin-iopipe/blob/master/example/serverless.yml) 58 | 59 | #### `iopipeToken` (optional) 60 | 61 | If not using the environment variable of `$IOPIPE_TOKEN`, the token of the project you would like to wrap your functions with. 62 | 63 | #### `iopipeNoVerify` (optional) 64 | 65 | Skip a check that ensures iopipe is installed via npm/yarn and present in package.json 66 | 67 | #### `iopipeNoUpgrade` (optional) 68 | 69 | The plugin automatically upgrades the IOpipe library to the latest available version that satisfies the semver range specified in package.json. Use this option to disable that feature. 70 | 71 | #### `iopipeNoYarn` (optional) 72 | 73 | When auto-upgrading, Yarn will be used in place of NPM if a yarn.lock file is found. Use this flag disable yarn and use NPM to upgrade the iopipe library. 74 | 75 | #### `iopipeExclude` (optional) 76 | 77 | Exclude certain lambda functions from being wrapped by the plugin. Comma separated string. 78 | 79 | #### `iopipeNoStats` (optional) 80 | 81 | By default, the plugin sends _anonymized_, non-identifying usage statistics to Google Analytics. IOpipe will use this info to prioritize updates and enhancements to the plugin. If you'd like to opt out of this, just set this option. 82 | 83 | #### `iopipeHandlerDir` (optional) 84 | 85 | Change the directory that the IOpipe handler files will be generated in. Defaults to `iopipe_handlers`. Note, watch out using directories beginning with a `.` character due to current bugs within Serverless framework and serverless-offline: 86 | - [serverless/issues/4633](https://github.com/serverless/serverless/issues/4633) 87 | - [serverless-offline/pull/346](https://github.com/dherault/serverless-offline/pull/346) 88 | 89 | ## FAQ 90 | - Does this work with webpack? 91 | - Yes, you can use this plugin with webpack or serverless plugins utilizing webpack. For best results, make sure this plugin is specified _before_ the webpack plugins in serverless.yml, i.e. 92 | ```yaml 93 | plugins: 94 | - serverless-plugin-iopipe 95 | - serverless-webpack 96 | ``` 97 | - Does this work with [serverless-offline](https://github.com/dherault/serverless-offline)? 98 | - Yes, list `serverless-plugin-iopipe` first before any other plugins in `serverless.yml`. 99 | - You will likely need to use the `iopipeHandlerDir` option to change where the IOpipe handler files are generated until [this PR is merged](https://github.com/dherault/serverless-offline/pull/346). 100 | - Can I use IOpipe plugins? 101 | - Yes, you can specify iopipe plugins through your [package.json file, or an iopipe.rc file](https://github.com/iopipe/iopipe-js-core#packagejson-configuration). Ensure those plugins are installed into your node_modules folder (yarn or npm). 102 | 103 | ## Known Issues 104 | - If you have lambda functions that are already wrapped by iopipe via code, you may experience unexpected results. Remove the iopipe wrapping code from those handlers. 105 | - If your `package.json` is located in a non-standard place, auto-upgrading may not work. 106 | - If attempting to use es6 modules natively i.e. `export function handler...`, may not work. 107 | 108 | ## Support 109 | File an issue here, hit us up [on Slack](https://iopipe.now.sh/), or send us a note at [support@iopipe.com](mailto:support@iopipe.com) 110 | 111 | ## Contributing 112 | - This project uses [Prettier](https://github.com/prettier/prettier). Please execute `npm run eslintFix` to auto-format the code before submitting pull requests. 113 | -------------------------------------------------------------------------------- /src/index.test.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable import/no-dynamic-require*/ 2 | import path from 'path'; 3 | import _ from 'lodash'; 4 | import { 5 | copySync, 6 | renameSync, 7 | removeSync, 8 | readdirSync, 9 | readFileSync 10 | } from 'fs-extra'; 11 | 12 | import sls from './__mocks__/sls'; 13 | 14 | const ServerlessPlugin = require('../dist/index'); 15 | 16 | let Plugin; 17 | const prefix = path.resolve(__dirname, '../testProjects/default'); 18 | 19 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; 20 | 21 | test('Can instantiate main class', () => { 22 | // allows missing package.json next to serverless.yml 23 | renameSync( 24 | path.resolve(prefix, 'package.json'), 25 | path.resolve(prefix, 'package1.json') 26 | ); 27 | // start the plugin 28 | Plugin = new ServerlessPlugin(sls, { 29 | prefix 30 | }); 31 | // reset package.json 32 | renameSync( 33 | path.resolve(prefix, 'package1.json'), 34 | path.resolve(prefix, 'package.json') 35 | ); 36 | expect(Plugin).toBeDefined(); 37 | }); 38 | 39 | test('Options module is a function', () => { 40 | expect(Plugin.getOptions).toBeInstanceOf(Function); 41 | }); 42 | 43 | test('Options are set with defaults', () => { 44 | let opts = Plugin.getOptions(); 45 | expect(opts.testInterpolate).toBeUndefined(); 46 | // set the options state as if we were triggering Plugin.run() 47 | sls.service.custom.iopipeTestInterpolate = 'wow-fun'; 48 | Plugin.setOptions({}); 49 | opts = Plugin.getOptions(); 50 | expect(opts).toBeDefined(); 51 | expect(opts).toHaveProperty('quote'); 52 | expect(opts.testInterpolate).toBe('wow-fun'); 53 | expect(opts.noVerify).toBeUndefined(); 54 | }); 55 | 56 | test('Plugin has props', () => { 57 | ['sls', 'package', 'funcs', 'commands', 'hooks'].forEach(str => { 58 | expect(Plugin).toHaveProperty(str); 59 | }); 60 | }); 61 | 62 | test('Plugin has proper executeable methods', () => { 63 | [ 64 | 'log', 65 | 'run', 66 | 'setPackage', 67 | 'setOptions', 68 | 'checkForLib', 69 | 'upgradeLib', 70 | 'checkToken', 71 | 'getFuncs', 72 | 'createFiles', 73 | 'assignHandlers', 74 | 'finish' 75 | ].forEach(str => { 76 | expect(Plugin[str]).toBeDefined(); 77 | expect(Plugin[str]).toBeInstanceOf(Function); 78 | }); 79 | }); 80 | 81 | test('Options are set via Plugin', () => { 82 | const opts = Plugin.getOptions(); 83 | expect(opts).toBeInstanceOf(Object); 84 | expect(opts.token).toEqual('SAMPLE_TOKEN_FOO'); 85 | }); 86 | 87 | test('Options can be overridden', () => { 88 | let opts = Plugin.getOptions(); 89 | expect(opts.exclude).toContain('excluded'); 90 | opts = Plugin.getOptions({ token: 'WOW_FUN_TOKEN' }); 91 | expect(opts.token).toEqual('WOW_FUN_TOKEN'); 92 | expect(opts.exclude).toContain('excluded'); 93 | }); 94 | 95 | test('Tracking works', async () => { 96 | const res = await Plugin.track({ action: 'dummy-test-action' }); 97 | expect(res).toEqual(1); 98 | }); 99 | 100 | test('Tracking noops when noStats is set', async () => { 101 | Plugin.getOptions({ noStats: true }); 102 | const res = await Plugin.track({ action: 'dummy-test-action' }); 103 | expect(res).toEqual('no-stats'); 104 | }); 105 | 106 | test('Package is set via Plugin', () => { 107 | expect(Plugin.package).toBeDefined(); 108 | expect(Plugin.package.dependencies).not.toBeDefined(); 109 | Plugin.setPackage(); 110 | expect(Plugin.package.dependencies).toBeDefined(); 111 | }); 112 | 113 | test('Can check for lib, all is well', () => { 114 | const check = Plugin.checkForLib(); 115 | expect(check).toBe(true); 116 | }); 117 | 118 | test('Skips lib check if package.json has no dependencies', () => { 119 | const check = Plugin.checkForLib({}); 120 | expect(check).toBe('no-package-skip'); 121 | }); 122 | 123 | test('Skips lib check if opts specify noVerify', () => { 124 | Plugin.getOptions({ noVerify: true }); 125 | const check = Plugin.checkForLib({ dependencies: {} }); 126 | expect(check).toBe('no-verify-skip'); 127 | Plugin.getOptions({ noVerify: false }); 128 | }); 129 | 130 | test('Throws error if iopipe is not found in valid package.json', () => { 131 | let targetErr; 132 | try { 133 | Plugin.checkForLib({ dependencies: { lodash: '4.17.4' } }); 134 | } catch (err) { 135 | targetErr = err; 136 | } 137 | expect(targetErr).toBeInstanceOf(Error); 138 | expect(targetErr.message).toMatch(/module not found/); 139 | }); 140 | 141 | test('Warns if iopipe token is not found', () => { 142 | Plugin.getOptions({ token: '' }); 143 | const msg = Plugin.checkToken(); 144 | expect(msg).toMatchSnapshot(); 145 | }); 146 | 147 | test('Does not upgrade if noUpgrade option is set', async () => { 148 | Plugin.getOptions({ noUpgrade: true }); 149 | const result = await Plugin.upgradeLib(); 150 | expect(result).toBe('no-upgrade'); 151 | }); 152 | 153 | test('Uses npm if no yarn.lock (no upgrade needed)', async () => { 154 | Plugin.getOptions({ noUpgrade: false }); 155 | renameSync( 156 | path.resolve(prefix, 'yarn.lock'), 157 | path.resolve(prefix, 'yarn1.lock') 158 | ); 159 | const upgradeResult = await Plugin.upgradeLib(); 160 | expect(upgradeResult).toBe('success-no-upgrade-npm'); 161 | renameSync( 162 | path.resolve(prefix, 'yarn1.lock'), 163 | path.resolve(prefix, 'yarn.lock') 164 | ); 165 | }); 166 | 167 | test('Uses yarn if available lockfile found (no upgrade needed)', async () => { 168 | const upgradeResult = await Plugin.upgradeLib(); 169 | expect(upgradeResult).toBe('success-no-upgrade-yarn'); 170 | }); 171 | 172 | async function upgrade(manager) { 173 | let err; 174 | try { 175 | //prepare dummy new package.json 176 | copySync( 177 | path.join(prefix, 'package.json'), 178 | path.join(prefix, 'packageOld.json') 179 | ); 180 | manager === 'npm' && 181 | renameSync( 182 | path.join(prefix, 'yarn.lock'), 183 | path.join(prefix, 'yarn1.lock') 184 | ); 185 | const upgradeResult = await Plugin.upgradeLib( 186 | '1.6.0', 187 | 'cd testProjects/default' 188 | ); 189 | expect(upgradeResult).toBe(`success-upgrade-${manager}-1.6.0`); 190 | //reset back to original 191 | } catch (e) { 192 | err = e; 193 | } 194 | removeSync(path.join(prefix, 'package.json')); 195 | renameSync( 196 | path.join(prefix, 'packageOld.json'), 197 | path.join(prefix, 'package.json') 198 | ); 199 | manager === 'npm' && 200 | renameSync(path.join(prefix, 'yarn1.lock'), path.join(prefix, 'yarn.lock')); 201 | if (err) { 202 | throw new Error(err); 203 | } 204 | return manager; 205 | } 206 | 207 | test('Upgrades lib with yarn', async () => { 208 | const test = await upgrade('yarn'); 209 | expect(test).toBe('yarn'); 210 | }); 211 | 212 | test('Upgrades lib with npm', async () => { 213 | const test = await upgrade('npm'); 214 | expect(test).toBe('npm'); 215 | }); 216 | 217 | test('Gets funcs', () => { 218 | expect(Plugin.funcs).toEqual(expect.arrayContaining([])); 219 | expect(sls.service.functions.python.runtime).toEqual('python2.7'); 220 | Plugin.getFuncs(); 221 | expect(_.find(Plugin.funcs, f => f.name === 'python')).toBeUndefined(); 222 | const simple = _.find(Plugin.funcs, f => f.name === 'simple'); 223 | expect(simple).toBeDefined(); 224 | ['handler', 'name', 'method', 'path', 'relativePath'].forEach(str => { 225 | expect(simple).toHaveProperty(str); 226 | }); 227 | }); 228 | 229 | test('Can create iopipe handler file', () => { 230 | Plugin.getOptions({ token: 'TEST_TOKEN' }); 231 | Plugin.createFiles(); 232 | const file = readFileSync( 233 | path.join(prefix, 'iopipe_handlers/simple-iopipe.js'), 234 | 'utf8' 235 | ); 236 | expect(file).toBeDefined(); 237 | expect(file).toMatchSnapshot(); 238 | }); 239 | 240 | test('Agent instantiation only includes installMethod if no iopipeToken in custom section of serverless.yml', () => { 241 | Plugin.getOptions({ token: '' }); 242 | Plugin.createFiles(); 243 | const file = readFileSync( 244 | path.join(prefix, 'iopipe_handlers/simple-iopipe.js'), 245 | 'utf8' 246 | ); 247 | expect(file).toBeDefined(); 248 | expect(file.split('\n')[0]).toMatchSnapshot(); 249 | }); 250 | 251 | test('Cleans up', () => { 252 | Plugin.finish(); 253 | const files = readdirSync(prefix); 254 | expect(_.includes(files, 'iopipe_handlers')).toBeFalsy(); 255 | expect(_.includes(files, 'serverless.yml')).toBeTruthy(); 256 | }); 257 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | https://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of yright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | Copyright 2015-2017, Erica Windisch. IOpipe, Inc. 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | https://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. 192 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { exec } from 'child_process'; 2 | import { join, posix } from 'path'; 3 | import _ from 'lodash'; 4 | import fs from 'fs-extra'; 5 | import debugLib from 'debug'; 6 | import cosmiconfig from 'cosmiconfig'; 7 | 8 | import thisPkg from '../package'; 9 | import { getVisitor, track } from './util/track'; 10 | import hrMillis from './util/hrMillis'; 11 | import handlerCode from './handlerCode'; 12 | 13 | function createDebugger(suffix) { 14 | return debugLib(`serverless-plugin-iopipe:${suffix}`); 15 | } 16 | 17 | function outputHandlerCode(obj = {}) { 18 | const { name, relativePath, method } = obj; 19 | const fnName = _.camelCase(`attempt-${name}`); 20 | return handlerCode 21 | .replace(/EXPORT_NAME/g, name) 22 | .replace(/FUNCTION_NAME/g, fnName) 23 | .replace(/RELATIVE_PATH/g, relativePath) 24 | .replace(/METHOD/g, method); 25 | } 26 | 27 | function getExitCode(stdout) { 28 | return _.chain(stdout) 29 | .defaultTo('') 30 | .split('\n') 31 | .compact() 32 | .last() 33 | .value(); 34 | } 35 | 36 | function getUpgradeVersion({ 37 | packageManager, 38 | suppliedTargetVersion, 39 | debug, 40 | installed, 41 | preCmd = '' 42 | }) { 43 | return new Promise((resolve, reject) => { 44 | exec( 45 | `${preCmd}${preCmd && 46 | ' && '}${packageManager} outdated ${installed} && echo $?`, 47 | (err, stdout = '', stderr = '') => { 48 | _.noop(err); 49 | const stdoutLines = _.chain(stdout) 50 | .split('\n') 51 | .map(s => _.trim(s)) 52 | .value(); 53 | const publishedVersions = _.chain(stdoutLines) 54 | .find((str = '') => str.match(installed)) 55 | .split(' ') 56 | .compact() 57 | .slice(1, 4) 58 | .value(); 59 | const [current, wanted, latest] = publishedVersions; 60 | // auto-upgrade to 1.0 since its major, but non-breaking 61 | const version = 62 | suppliedTargetVersion || 63 | (current !== latest && latest.match(/^1\./) && latest) || 64 | wanted; 65 | debug(`From ${packageManager} outdated command: `, stdoutLines); 66 | if (version) { 67 | return resolve(version); 68 | } else if (getExitCode(stdout) === '0') { 69 | return resolve(true); 70 | } 71 | return reject(stderr); 72 | } 73 | ); 74 | }); 75 | } 76 | 77 | function runUpgrade(pluginInstance, packageManager, version, preCmd, debug) { 78 | return new Promise((resolve, reject) => { 79 | debug(`Attempting to upgrade to ${version}`); 80 | // write package.json to file 81 | fs.writeFileSync( 82 | join(pluginInstance.prefix, 'package.json'), 83 | JSON.stringify(pluginInstance.package, null, ' ') 84 | ); 85 | debug(`Executing ${packageManager} install`); 86 | return exec( 87 | `${preCmd} && ${packageManager} install && echo $?`, 88 | (err, stdout = '', stderr = '') => { 89 | if (err) { 90 | return reject(err); 91 | } 92 | return getExitCode(stdout) === '0' ? resolve(true) : reject(stderr); 93 | } 94 | ); 95 | }); 96 | } 97 | 98 | class ServerlessIOpipePlugin { 99 | constructor(sls = {}, opts) { 100 | this.sls = sls; 101 | this.prefix = 102 | opts.prefix || 103 | this.sls.config.servicePath || 104 | process.env.npm_config_prefix; 105 | this.visitor = getVisitor(this); 106 | this.package = {}; 107 | this.funcs = []; 108 | this.originalServicePath = this.sls.config.servicePath; 109 | this.commands = { 110 | iopipe: { 111 | usage: 112 | "Automatically wraps your function handlers in IOpipe, so you don't have to.", 113 | lifecycleEvents: ['run', 'clean'], 114 | commands: { 115 | clean: { 116 | usage: 'Cleans up extra IOpipe files if necessary', 117 | lifecycleEvents: ['init'] 118 | } 119 | } 120 | } 121 | }; 122 | this.hooks = { 123 | 'iopipe:run': this.greeting.bind(this), 124 | 'before:package:createDeploymentArtifacts': this.run.bind(this), 125 | 'before:deploy:function:packageFunction': this.run.bind(this), 126 | 'before:invoke:local:invoke': this.run.bind(this), 127 | 'before:offline:start:init': this.run.bind(this), 128 | 'before:step-functions-offline:start': this.run.bind(this), 129 | 'after:package:createDeploymentArtifacts': this.finish.bind(this), 130 | 'after:invoke:local:invoke': this.finish.bind(this), 131 | 'iopipe:clean:init': this.finish.bind(this) 132 | }; 133 | } 134 | getOptions(obj = this.options) { 135 | this.options = _.chain(obj) 136 | .defaults(this.options) 137 | .defaults({ 138 | quote: 'single', 139 | handlerDir: 'iopipe_handlers' 140 | }) 141 | .mapKeys((val, key) => _.camelCase(key)) 142 | .value(); 143 | return this.options; 144 | } 145 | getInstalledPackageName({ dependencies } = this.package) { 146 | return ['@iopipe/iopipe', '@iopipe/core', 'iopipe'].find(s => 147 | _.keys(dependencies).find(n => n === s) 148 | ); 149 | } 150 | log(arg1, ...rest) { 151 | //sls doesn't actually support multiple args to log? 152 | /*eslint-disable no-console*/ 153 | const logger = this.sls.cli.log || console.log; 154 | /*eslint-enable no-console*/ 155 | logger.call(this.sls.cli, `serverless-plugin-iopipe: ${arg1}`, ...rest); 156 | } 157 | track(kwargs) { 158 | return track(this, kwargs); 159 | } 160 | greeting() { 161 | this.log( 162 | 'Welcome to the IOpipe Serverless plugin. You can use this plugin for sls invoke local or sls deploy. Make sure you have the $IOPIPE_TOKEN environment variable set documented here: https://github.com/iopipe/serverless-plugin-iopipe#install.' 163 | ); 164 | } 165 | async run() { 166 | const start = process.hrtime(); 167 | this.setOptions({}); 168 | this.track({ 169 | action: 'run-start' 170 | }); 171 | this.log('Wrapping your functions with IO|...'); 172 | this.setPackage(); 173 | this.checkForLib(); 174 | this.checkToken(); 175 | await this.upgradeLib(); 176 | this.getFuncs(); 177 | this.createFiles(); 178 | this.assignHandlers(); 179 | this.track({ 180 | action: 'run-finish', 181 | value: hrMillis(start) 182 | }); 183 | } 184 | setPackage() { 185 | try { 186 | this.package = fs.readJsonSync(join(this.prefix, 'package.json')); 187 | } catch (err) { 188 | this.package = {}; 189 | } 190 | } 191 | setOptions(opts) { 192 | const debug = createDebugger('setOptions'); 193 | const custom = _.chain(this.sls) 194 | .get('service.custom') 195 | .pickBy((val, key) => key.match(/^iopipe/)) 196 | .mapKeys((val, key) => _.camelCase(key.replace(/^iopipe/, ''))) 197 | .mapValues((val, key) => { 198 | if (key === 'exclude' && _.isString(val)) { 199 | return val.split(','); 200 | } 201 | return val; 202 | }) 203 | .value(); 204 | const envVars = _.chain(process.env) 205 | .pickBy((val, key) => key.match(/^IOPIPE/)) 206 | .mapKeys((val, key) => _.camelCase(key.replace(/^IOPIPE/, ''))) 207 | .value(); 208 | const val = _.defaults(opts, custom, envVars); 209 | debug('Options object:', val); 210 | this.track({ 211 | action: 'options-set', 212 | value: val 213 | }); 214 | this.getOptions(val); 215 | } 216 | checkForLib(pack = this.package) { 217 | const installed = this.getInstalledPackageName(pack); 218 | if (_.isEmpty(pack) || !_.isPlainObject(pack)) { 219 | this.track({ 220 | action: 'no-package-skip-lib-check' 221 | }); 222 | this.log('No package.json found, skipping lib check.'); 223 | return 'no-package-skip'; 224 | } else if (_.isPlainObject(pack) && !installed) { 225 | if (this.getOptions().noVerify) { 226 | this.log('Skipping iopipe module installation check.'); 227 | return 'no-verify-skip'; 228 | } 229 | this.track({ 230 | action: 'lib-not-found' 231 | }); 232 | throw new Error( 233 | 'IOpipe module not found in package.json. Make sure to install it via npm or yarn, or use the --noVerify option for serverless-plugin-iopipe.' 234 | ); 235 | } 236 | return true; 237 | } 238 | checkToken() { 239 | const token = this.getOptions().token; 240 | if (!token) { 241 | const msg = 242 | 'You did not specify iopipeToken in your custom section of serverless.yml. iopipe will fall back to $IOPIPE_TOKEN in the lambda environment'; 243 | this.log(msg); 244 | return msg; 245 | } 246 | return true; 247 | } 248 | async upgradeLib(suppliedTargetVersion, preCmd = 'echo Installing.') { 249 | if (this.getOptions().noUpgrade) { 250 | return 'no-upgrade'; 251 | } 252 | const debug = createDebugger('upgrade'); 253 | const files = fs.readdirSync(this.prefix); 254 | const useYarn = _.includes(files, 'yarn.lock'); 255 | const packageManager = useYarn ? 'yarn' : 'npm'; 256 | debug(`Using pkg manager: ${packageManager}`); 257 | this.track({ 258 | action: 'lib-upgrade', 259 | label: packageManager 260 | }); 261 | let version; 262 | 263 | const installed = this.getInstalledPackageName(); 264 | 265 | // Get the version of iopipe that we need to upgrade to, if necessary 266 | try { 267 | version = await getUpgradeVersion({ 268 | packageManager, 269 | suppliedTargetVersion, 270 | debug, 271 | installed, 272 | preCmd 273 | }); 274 | if (version === true) { 275 | this.log('You have the latest IOpipe library. Nice work!'); 276 | return `success-no-upgrade-${packageManager}`; 277 | } 278 | } catch (err) { 279 | this.log('Could not finish upgrading IOpipe automatically.'); 280 | debug(`Err from ${packageManager} outdated:`, err); 281 | this.track({ 282 | action: `${packageManager}-outdated-error`, 283 | value: err 284 | }); 285 | return `${packageManager}-outdated-error`; 286 | } 287 | 288 | // If we have a version that we now need to upgrade to, lets upgrade 289 | try { 290 | this.package.dependencies[installed] = version; 291 | await runUpgrade(this, packageManager, version, preCmd, debug); 292 | } catch (err) { 293 | this.log(err); 294 | this.track({ 295 | action: 'lib-upgrade-error', 296 | value: err 297 | }); 298 | return `err-install-${packageManager}`; 299 | } 300 | this.track({ 301 | action: 'lib-upgrade-success', 302 | value: true 303 | }); 304 | this.log(`Upgraded ${installed} to ${version} automatically. 💪`); 305 | return `success-upgrade-${packageManager}-${version}`; 306 | } 307 | getFuncs() { 308 | try { 309 | const { servicePath } = this.sls.config; 310 | this.funcs = _.chain(this.sls.service.functions) 311 | .omit(this.getOptions().exclude) 312 | .toPairs() 313 | //filter out functions that are not Node.js 314 | .reject(arr => { 315 | const key = arr[0]; 316 | const obj = arr[1]; 317 | if (_.isString(obj.runtime) && !obj.runtime.match('node')) { 318 | this.log( 319 | `Function "${key}" is not Node.js. Currently the plugin only supports Node.js functions. Skipping ${key}.` 320 | ); 321 | return true; 322 | } 323 | return false; 324 | }) 325 | .map(arr => { 326 | const [key, obj] = arr; 327 | const handlerArr = _.isString(obj.handler) 328 | ? obj.handler.split('.') 329 | : []; 330 | const relativePath = handlerArr.slice(0, -1).join('.'); 331 | const path = `${servicePath}/${relativePath}.js`; 332 | return _.assign({}, obj, { 333 | method: _.last(handlerArr), 334 | path, 335 | name: key, 336 | relativePath, 337 | file: _.last((handlerArr.slice(-2, -1)[0] || '').split('/')) 338 | }); 339 | }) 340 | .value(); 341 | this.track({ 342 | action: 'funcs-count', 343 | value: this.funcs.length 344 | }); 345 | } catch (err) { 346 | this.track({ 347 | action: 'get-funcs-fail', 348 | value: err 349 | }); 350 | /*eslint-disable no-console*/ 351 | console.error('Failed to read functions from serverless.yml.'); 352 | /*eslint-enable no-console*/ 353 | throw new Error(err); 354 | } 355 | } 356 | getConfig() { 357 | const { token } = this.getOptions(); 358 | const { config: cosmi = {} } = 359 | cosmiconfig('iopipe', { 360 | cache: false, 361 | sync: true, 362 | rcExtensions: true 363 | }).load(process.cwd()) || {}; 364 | 365 | const plugins = (cosmi.plugins || []).map(plugin => { 366 | // plugins can be specified as strings or as arrays with 2 entries 367 | // ["@iopipe/trace", ["@iopipe/logger", {"enabled": true}]] 368 | // create require calls for each scenario 369 | const pluginModule = _.isArray(plugin) ? plugin[0] : plugin; 370 | const pluginConfig = _.isArray(plugin) ? JSON.stringify(plugin[1]) : ''; 371 | return `require('${pluginModule}')(${pluginConfig})`; 372 | }); 373 | 374 | const inlineConfigObject = _.pickBy( 375 | _.assign({}, cosmi, { 376 | token, 377 | installMethod: `${thisPkg.name}@${thisPkg.version}`, 378 | // ⬇ this will be replaced with plugin require block that cannot be JSON.stringified 379 | plugins: 'xxx' 380 | }) 381 | ); 382 | 383 | let inlineConfig = JSON.stringify(inlineConfigObject); 384 | inlineConfig = inlineConfig.replace( 385 | /"plugins":"xxx"/, 386 | `"plugins":[${plugins.join(',')}]` 387 | ); 388 | 389 | return { 390 | inlineConfig 391 | }; 392 | } 393 | createFiles() { 394 | const debug = createDebugger('createFiles'); 395 | debug('Creating file'); 396 | const { inlineConfig } = this.getConfig(); 397 | const { handlerDir } = this.getOptions(); 398 | const iopipeInclude = `const iopipe = require('${this.getInstalledPackageName()}')(${inlineConfig});`; 399 | this.funcs.forEach(func => { 400 | const handler = outputHandlerCode(func); 401 | const contents = `${iopipeInclude}\n\n${handler}`; 402 | fs.ensureDirSync(join(this.originalServicePath, handlerDir)); 403 | fs.writeFileSync( 404 | join( 405 | this.originalServicePath, 406 | join(handlerDir, `${func.name}-iopipe.js`) 407 | ), 408 | contents 409 | ); 410 | }); 411 | } 412 | assignHandlers() { 413 | const debug = createDebugger('assignHandlers'); 414 | debug('Assigning iopipe handlers to sls service'); 415 | const { handlerDir } = this.getOptions(); 416 | this.funcs.forEach(obj => { 417 | _.set( 418 | this.sls.service.functions, 419 | `${obj.name}.handler`, 420 | posix.join(handlerDir, `${obj.name}-iopipe.${obj.name}`) 421 | ); 422 | }); 423 | } 424 | finish() { 425 | const debug = createDebugger('finish'); 426 | this.log('Cleaning up extraneous IOpipe files'); 427 | debug(`Removing ${this.handlerFileName}.js`); 428 | const { handlerDir = 'iopipe_handlers' } = this.getOptions(); 429 | fs.removeSync(join(this.originalServicePath, handlerDir)); 430 | this.track({ 431 | action: 'finish' 432 | }) 433 | .then(_.noop) 434 | .catch(debug); 435 | } 436 | } 437 | 438 | module.exports = ServerlessIOpipePlugin; 439 | -------------------------------------------------------------------------------- /src/__mocks__/sls.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable max-lines*/ 2 | /*eslint-disable quotes*/ 3 | import path from 'path'; 4 | 5 | export default { 6 | providers: { 7 | aws: { 8 | naming: { 9 | provider: '~providers~aws' 10 | }, 11 | options: { 12 | noDeploy: true, 13 | stage: 'prod', 14 | region: 'us-west-2', 15 | token: 'SAMPLE_TOKEN_FOO', 16 | quote: 'double', 17 | exclude: ['excluded', 'foo'], 18 | placeholder: false 19 | }, 20 | provider: '~providers~aws', 21 | serverless: '~', 22 | sdk: { 23 | util: { 24 | base64: {}, 25 | buffer: {}, 26 | string: {}, 27 | ini: {}, 28 | fn: {}, 29 | date: {}, 30 | crypto: { 31 | crc32Table: [0], 32 | lib: { 33 | DEFAULT_ENCODING: 'buffer', 34 | constants: {} 35 | } 36 | }, 37 | abort: {}, 38 | uuid: {}, 39 | domain: { 40 | _stack: [], 41 | active: null 42 | }, 43 | url: {}, 44 | querystring: {} 45 | }, 46 | VERSION: '2.40.0', 47 | Signers: {}, 48 | Protocol: { 49 | Json: {}, 50 | Query: {}, 51 | Rest: {}, 52 | RestJson: {}, 53 | RestXml: {} 54 | }, 55 | XML: {}, 56 | JSON: {}, 57 | Model: {}, 58 | config: { 59 | credentials: { 60 | expired: false, 61 | expireTime: null, 62 | accessKeyId: '', 63 | filename: '', 64 | profile: 'default', 65 | disableAssumeRole: true 66 | }, 67 | credentialProvider: { 68 | providers: [null, null, null, null] 69 | }, 70 | logger: null, 71 | apiVersions: {}, 72 | apiVersion: null, 73 | httpOptions: { 74 | timeout: 120000 75 | }, 76 | maxRedirects: 10, 77 | paramValidation: true, 78 | sslEnabled: true, 79 | s3ForcePathStyle: false, 80 | s3BucketEndpoint: false, 81 | s3DisableBodySigning: true, 82 | computeChecksums: true, 83 | convertResponseTypes: true, 84 | correctClockSkew: false, 85 | customUserAgent: null, 86 | dynamoDbCrc32: true, 87 | systemClockOffset: 0, 88 | signatureVersion: null, 89 | signatureCache: true, 90 | retryDelayOptions: {}, 91 | useAccelerateEndpoint: false 92 | }, 93 | EventListeners: { 94 | Core: { 95 | _events: { 96 | validate: [null, null, null, null], 97 | afterBuild: [null, null, null], 98 | restart: [null], 99 | sign: [null], 100 | validateResponse: [null], 101 | send: [null], 102 | httpHeaders: [null], 103 | httpData: [null], 104 | httpDone: [null], 105 | retry: [null, null, null, null, null, null], 106 | afterRetry: [null] 107 | } 108 | }, 109 | CorePost: { 110 | _events: { 111 | extractData: [null], 112 | extractError: [null], 113 | httpError: [null] 114 | } 115 | }, 116 | Logger: { 117 | _events: { 118 | complete: [null] 119 | } 120 | }, 121 | Json: { 122 | _events: { 123 | build: [null], 124 | extractData: [null], 125 | extractError: [null] 126 | } 127 | }, 128 | Rest: { 129 | _events: { 130 | build: [null], 131 | extractData: [null], 132 | extractError: [null] 133 | } 134 | }, 135 | RestJson: { 136 | _events: { 137 | build: [null], 138 | extractData: [null], 139 | extractError: [null] 140 | } 141 | }, 142 | RestXml: { 143 | _events: { 144 | build: [null], 145 | extractData: [null], 146 | extractError: [null] 147 | } 148 | }, 149 | Query: { 150 | _events: { 151 | build: [null], 152 | extractData: [null], 153 | extractError: [null] 154 | } 155 | } 156 | }, 157 | events: { 158 | _events: {} 159 | } 160 | } 161 | } 162 | }, 163 | version: '1.10.2', 164 | yamlParser: { 165 | serverless: '~' 166 | }, 167 | utils: { 168 | serverless: '~' 169 | }, 170 | service: { 171 | serverless: '~', 172 | service: 'sls-iopipe', 173 | provider: { 174 | stage: 'prod', 175 | region: 'us-west-2', 176 | /*eslint-disable no-template-curly-in-string*/ 177 | variableSyntax: '\\${([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}', 178 | name: 'aws', 179 | runtime: 'nodejs6.10', 180 | versionFunctions: true, 181 | compiledCloudFormationTemplate: {} 182 | }, 183 | custom: { 184 | iopipeToken: 'SAMPLE_TOKEN_FOO', 185 | iopipeQuote: 'double', 186 | iopipeExclude: 'excluded,foo', 187 | iopipePlaceholder: false 188 | }, 189 | plugins: ['serverless-plugin-iopipe/index.js'], 190 | functions: { 191 | simple: { 192 | handler: 'handlers/simple.handler', 193 | events: [], 194 | name: 'sls-iopipe-prod-simple' 195 | }, 196 | multiple: { 197 | handler: 'handlers/multiple.handler', 198 | events: [], 199 | name: 'sls-iopipe-prod-multiple' 200 | }, 201 | multipleDifferentHandler: { 202 | handler: 'handlers/multiple.differentNameHandler', 203 | events: [], 204 | name: 'sls-iopipe-prod-multiple-different-handler' 205 | }, 206 | es5: { 207 | handler: 'handlers/es5.handler', 208 | events: [], 209 | name: 'sls-iopipe-prod-es5' 210 | }, 211 | 'multiple-dots-in-name': { 212 | handler: 'handlers/multiple.dots.in.name.handler', 213 | events: [], 214 | name: 'sls-iopipe-prod-multiple-dots-in-name' 215 | }, 216 | noModule: { 217 | handler: 'handlers/noModule.handler', 218 | events: [], 219 | name: 'sls-iopipe-prod-noModule' 220 | }, 221 | syntaxError: { 222 | handler: 'handlers/syntaxError.handler', 223 | events: [], 224 | name: 'sls-iopipe-prod-syntaxError' 225 | }, 226 | excluded: { 227 | handler: 'handlers/excluded.handler', 228 | events: [], 229 | name: 'sls-iopipe-prod-excluded' 230 | }, 231 | python: { 232 | handler: 'python/main.longRunning', 233 | runtime: 'python2.7' 234 | } 235 | }, 236 | package: { 237 | artifact: 'testProject/.iopipe/.serverless/sls-iopoipe.zip' 238 | } 239 | }, 240 | variables: { 241 | serverless: '~', 242 | service: '~service', 243 | overwriteSyntax: {}, 244 | fileRefSyntax: {}, 245 | envRefSyntax: {}, 246 | optRefSyntax: {}, 247 | selfRefSyntax: {}, 248 | options: '~providers~aws~options', 249 | variableSyntax: {} 250 | }, 251 | pluginManager: { 252 | serverless: '~', 253 | cliOptions: '~providers~aws~options', 254 | cliCommands: ['deploy'], 255 | plugins: [ 256 | { 257 | serverless: '~', 258 | options: '~providers~aws~options', 259 | commands: { 260 | config: { 261 | usage: 'Configure Serverless', 262 | commands: { 263 | credentials: { 264 | usage: 265 | 'Configures a new provider profile for the Serverless Framework', 266 | lifecycleEvents: ['config'], 267 | options: { 268 | provider: { 269 | usage: 'Name of the provider. Supported providers: "aws"', 270 | required: true, 271 | shortcut: 'p' 272 | } 273 | } 274 | } 275 | } 276 | } 277 | }, 278 | hooks: {} 279 | }, 280 | { 281 | serverless: '~', 282 | options: '~providers~aws~options', 283 | commands: { 284 | create: { 285 | usage: 'Create new Serverless service', 286 | lifecycleEvents: ['create'], 287 | options: { 288 | template: { 289 | usage: 290 | 'Template for the service. Available templates: "aws-nodejs", "aws-python", "aws-groovy-gradle", "aws-java-maven", "aws-java-gradle", "aws-scala-sbt", "aws-csharp", "azure-nodejs", "openwhisk-nodejs" and "plugin"', 291 | required: true, 292 | shortcut: 't' 293 | }, 294 | path: { 295 | usage: 296 | 'The path where the service should be created (e.g. --path my-service)', 297 | shortcut: 'p' 298 | }, 299 | name: { 300 | usage: 301 | 'Name for the service. Overwrites the default name of the created service.', 302 | shortcut: 'n' 303 | } 304 | } 305 | } 306 | }, 307 | hooks: {} 308 | }, 309 | { 310 | serverless: '~', 311 | options: '~providers~aws~options', 312 | commands: { 313 | install: { 314 | usage: 'Install a Serverless service from GitHub', 315 | lifecycleEvents: ['install'], 316 | options: { 317 | url: { 318 | usage: 'URL of the Serverless service on GitHub', 319 | required: true, 320 | shortcut: 'u' 321 | }, 322 | name: { 323 | usage: 'Name for the service', 324 | shortcut: 'n' 325 | } 326 | } 327 | } 328 | }, 329 | hooks: {} 330 | }, 331 | { 332 | serverless: '~', 333 | options: '~providers~aws~options', 334 | defaultExcludes: [ 335 | '.git/**', 336 | '.gitignore', 337 | '.DS_Store', 338 | 'npm-debug.log', 339 | 'serverless.yaml', 340 | 'serverless.yml', 341 | '.serverless/**' 342 | ], 343 | hooks: {} 344 | }, 345 | { 346 | serverless: '~', 347 | commands: { 348 | deploy: { 349 | usage: 'Deploy a Serverless service', 350 | lifecycleEvents: [ 351 | 'cleanup', 352 | 'initialize', 353 | 'setupProviderConfiguration', 354 | 'createDeploymentArtifacts', 355 | 'compileFunctions', 356 | 'compileEvents', 357 | 'deploy' 358 | ], 359 | options: { 360 | stage: { 361 | usage: 'Stage of the service', 362 | shortcut: 's' 363 | }, 364 | region: { 365 | usage: 'Region of the service', 366 | shortcut: 'r' 367 | }, 368 | noDeploy: { 369 | usage: 'Build artifacts without deploying', 370 | shortcut: 'n' 371 | }, 372 | verbose: { 373 | usage: 'Show all stack events during deployment', 374 | shortcut: 'v' 375 | } 376 | }, 377 | commands: { 378 | function: { 379 | usage: 'Deploy a single function from the service', 380 | lifecycleEvents: ['initialize', 'packageFunction', 'deploy'], 381 | options: { 382 | function: { 383 | usage: 'Name of the function', 384 | shortcut: 'f', 385 | required: true 386 | }, 387 | stage: { 388 | usage: 'Stage of the function', 389 | shortcut: 's' 390 | }, 391 | region: { 392 | usage: 'Region of the function', 393 | shortcut: 'r' 394 | } 395 | } 396 | }, 397 | list: { 398 | usage: 'List deployed version of your Serverless Service', 399 | lifecycleEvents: ['log'] 400 | } 401 | } 402 | } 403 | } 404 | }, 405 | { 406 | serverless: '~', 407 | commands: { 408 | invoke: { 409 | usage: 'Invoke a deployed function', 410 | lifecycleEvents: ['invoke'], 411 | options: { 412 | function: { 413 | usage: 'The function name', 414 | required: true, 415 | shortcut: 'f' 416 | }, 417 | stage: { 418 | usage: 'Stage of the service', 419 | shortcut: 's' 420 | }, 421 | region: { 422 | usage: 'Region of the service', 423 | shortcut: 'r' 424 | }, 425 | path: { 426 | usage: 'Path to JSON or YAML file holding input data', 427 | shortcut: 'p' 428 | }, 429 | type: { 430 | usage: 'Type of invocation', 431 | shortcut: 't' 432 | }, 433 | log: { 434 | usage: 'Trigger logging data output', 435 | shortcut: 'l' 436 | }, 437 | data: { 438 | usage: 'input data', 439 | shortcut: 'd' 440 | } 441 | }, 442 | commands: { 443 | local: { 444 | usage: 'Invoke function locally', 445 | lifecycleEvents: ['invoke'], 446 | options: { 447 | function: { 448 | usage: 'Name of the function', 449 | shortcut: 'f', 450 | required: true 451 | }, 452 | path: { 453 | usage: 'Path to JSON or YAML file holding input data', 454 | shortcut: 'p' 455 | }, 456 | data: { 457 | usage: 'input data', 458 | shortcut: 'd' 459 | } 460 | } 461 | } 462 | } 463 | } 464 | } 465 | }, 466 | { 467 | serverless: '~', 468 | commands: { 469 | info: { 470 | usage: 'Display information about the service', 471 | lifecycleEvents: ['info'], 472 | options: { 473 | stage: { 474 | usage: 'Stage of the service', 475 | shortcut: 's' 476 | }, 477 | region: { 478 | usage: 'Region of the service', 479 | shortcut: 'r' 480 | }, 481 | verbose: { 482 | usage: 'Display Stack output', 483 | shortcut: 'v' 484 | } 485 | } 486 | } 487 | } 488 | }, 489 | { 490 | serverless: '~', 491 | commands: { 492 | logs: { 493 | usage: 'Output the logs of a deployed function', 494 | lifecycleEvents: ['logs'], 495 | options: { 496 | function: { 497 | usage: 'The function name', 498 | required: true, 499 | shortcut: 'f' 500 | }, 501 | stage: { 502 | usage: 'Stage of the service', 503 | shortcut: 's' 504 | }, 505 | region: { 506 | usage: 'Region of the service', 507 | shortcut: 'r' 508 | }, 509 | tail: { 510 | usage: 'Tail the log output', 511 | shortcut: 't' 512 | }, 513 | startTime: { 514 | usage: 'Logs before this time will not be displayed' 515 | }, 516 | filter: { 517 | usage: 'A filter pattern' 518 | }, 519 | interval: { 520 | usage: 'Tail polling interval in milliseconds. Default: `1000`', 521 | shortcut: 'i' 522 | } 523 | } 524 | } 525 | } 526 | }, 527 | { 528 | serverless: '~', 529 | options: '~providers~aws~options', 530 | commands: { 531 | metrics: { 532 | usage: 'Show metrics for a specific function', 533 | lifecycleEvents: ['metrics'], 534 | options: { 535 | function: { 536 | usage: 'The function name', 537 | shortcut: 'f' 538 | }, 539 | stage: { 540 | usage: 'Stage of the service', 541 | shortcut: 's' 542 | }, 543 | region: { 544 | usage: 'Region of the service', 545 | shortcut: 'r' 546 | }, 547 | startTime: { 548 | usage: 'Start time for the metrics retrieval (e.g. 1970-01-01)' 549 | }, 550 | endTime: { 551 | usage: 'End time for the metrics retrieval (e.g. 1970-01-01)' 552 | } 553 | } 554 | } 555 | } 556 | }, 557 | { 558 | serverless: '~', 559 | commands: { 560 | remove: { 561 | usage: 'Remove Serverless service and all resources', 562 | lifecycleEvents: ['remove'], 563 | options: { 564 | stage: { 565 | usage: 'Stage of the service', 566 | shortcut: 's' 567 | }, 568 | region: { 569 | usage: 'Region of the service', 570 | shortcut: 'r' 571 | }, 572 | verbose: { 573 | usage: 'Show all stack events during deployment', 574 | shortcut: 'v' 575 | } 576 | } 577 | } 578 | } 579 | }, 580 | { 581 | serverless: '~', 582 | commands: { 583 | rollback: { 584 | usage: 'Rollback the Serverless service to a specific deployment', 585 | lifecycleEvents: ['initialize', 'rollback'], 586 | options: { 587 | timestamp: { 588 | usage: 589 | 'Timestamp of the deployment (list deployments with `serverless deploy list`)', 590 | shortcut: 't', 591 | required: true 592 | }, 593 | verbose: { 594 | usage: 'Show all stack events during deployment', 595 | shortcut: 'v' 596 | } 597 | } 598 | } 599 | } 600 | }, 601 | { 602 | serverless: '~', 603 | options: '~providers~aws~options', 604 | commands: { 605 | slstats: { 606 | usage: 'Enable or disable stats', 607 | lifecycleEvents: ['slstats'], 608 | options: { 609 | enable: { 610 | usage: 'Enable stats ("--enable")', 611 | shortcut: 'e' 612 | }, 613 | disable: { 614 | usage: 'Disable stats ("--disable")', 615 | shortcut: 'd' 616 | } 617 | } 618 | } 619 | }, 620 | hooks: {} 621 | }, 622 | { 623 | serverless: '~', 624 | options: '~providers~aws~options', 625 | commands: { 626 | config: { 627 | commands: { 628 | credentials: { 629 | lifecycleEvents: ['config'], 630 | options: { 631 | key: { 632 | usage: 'Access key for the provider', 633 | shortcut: 'k', 634 | required: true 635 | }, 636 | secret: { 637 | usage: 'Secret key for the provider', 638 | shortcut: 's', 639 | required: true 640 | }, 641 | profile: { 642 | usage: 643 | 'Name of the profile you wish to create. Defaults to "default"', 644 | shortcut: 'n' 645 | } 646 | } 647 | } 648 | } 649 | } 650 | }, 651 | hooks: {} 652 | }, 653 | '~providers~aws', 654 | { 655 | serverless: '~', 656 | options: '~providers~aws~options', 657 | provider: '~providers~aws', 658 | hooks: {} 659 | }, 660 | { 661 | serverless: '~', 662 | options: '~providers~aws~options', 663 | provider: '~providers~aws', 664 | hooks: {} 665 | }, 666 | { 667 | serverless: '~', 668 | provider: '~providers~aws', 669 | options: '~providers~aws~options', 670 | hooks: {} 671 | }, 672 | { 673 | serverless: '~', 674 | options: '~providers~aws~options', 675 | provider: '~providers~aws', 676 | hooks: {} 677 | }, 678 | { 679 | serverless: '~', 680 | options: '~providers~aws~options', 681 | provider: '~providers~aws', 682 | hooks: {} 683 | }, 684 | { 685 | serverless: '~', 686 | options: '~providers~aws~options', 687 | provider: '~providers~aws', 688 | hooks: {} 689 | }, 690 | { 691 | serverless: '~', 692 | options: '~providers~aws~options', 693 | provider: '~providers~aws', 694 | hooks: {} 695 | }, 696 | { 697 | serverless: '~', 698 | options: '~providers~aws~options', 699 | provider: '~providers~aws', 700 | hooks: {} 701 | }, 702 | { 703 | serverless: '~', 704 | provider: '~providers~aws', 705 | hooks: {} 706 | }, 707 | { 708 | serverless: '~', 709 | provider: '~providers~aws', 710 | hooks: {} 711 | }, 712 | { 713 | serverless: '~', 714 | options: '~providers~aws~options', 715 | provider: '~providers~aws', 716 | DEFAULT_JSON_REQUEST_TEMPLATE: 717 | '\n #set( $body = $input.json("$") )\n\n \n #define( $loop )\n {\n #foreach($key in $map.keySet())\n #set( $k = $util.escapeJavaScript($key) )\n #set( $v = $util.escapeJavaScript($map.get($key)).replaceAll("\\\\\'", "\'") )\n "$k":\n "$v"\n #if( $foreach.hasNext ) , #end\n #end\n }\n #end\n\n {\n "body": $body,\n "method": "$context.httpMethod",\n "principalId": "$context.authorizer.principalId",\n "stage": "$context.stage",\n\n "cognitoPoolClaims" : {\n extraCognitoPoolClaims\n "sub": "$context.authorizer.claims.sub"\n },\n\n #set( $map = $input.params().header )\n "headers": $loop,\n\n #set( $map = $input.params().querystring )\n "query": $loop,\n\n #set( $map = $input.params().path )\n "path": $loop,\n\n #set( $map = $context.identity )\n "identity": $loop,\n\n #set( $map = $stageVariables )\n "stageVariables": $loop\n }\n\n ', 718 | DEFAULT_FORM_URL_ENCODED_REQUEST_TEMPLATE: 719 | '\n #define( $body )\n {\n #foreach( $token in $input.path(\'$\').split(\'&\') )\n #set( $keyVal = $token.split(\'=\') )\n #set( $keyValSize = $keyVal.size() )\n #if( $keyValSize >= 1 )\n #set( $key = $util.escapeJavaScript($util.urlDecode($keyVal[0])) )\n #if( $keyValSize >= 2 )\n #set($val = $util.escapeJavaScript($util.urlDecode($keyVal[1])).replaceAll("\\\\\'","\'"))\n #else\n #set( $val = \'\' )\n #end\n "$key": "$val"#if($foreach.hasNext),#end\n #end\n #end\n }\n #end\n\n \n #define( $loop )\n {\n #foreach($key in $map.keySet())\n #set( $k = $util.escapeJavaScript($key) )\n #set( $v = $util.escapeJavaScript($map.get($key)).replaceAll("\\\\\'", "\'") )\n "$k":\n "$v"\n #if( $foreach.hasNext ) , #end\n #end\n }\n #end\n\n {\n "body": $body,\n "method": "$context.httpMethod",\n "principalId": "$context.authorizer.principalId",\n "stage": "$context.stage",\n\n "cognitoPoolClaims" : {\n extraCognitoPoolClaims\n "sub": "$context.authorizer.claims.sub"\n },\n\n #set( $map = $input.params().header )\n "headers": $loop,\n\n #set( $map = $input.params().querystring )\n "query": $loop,\n\n #set( $map = $input.params().path )\n "path": $loop,\n\n #set( $map = $context.identity )\n "identity": $loop,\n\n #set( $map = $stageVariables )\n "stageVariables": $loop\n }\n\n ', 720 | hooks: {} 721 | }, 722 | { 723 | serverless: '~', 724 | provider: '~providers~aws', 725 | hooks: {} 726 | }, 727 | { 728 | serverless: '~', 729 | provider: '~providers~aws', 730 | hooks: {} 731 | }, 732 | { 733 | serverless: '~', 734 | provider: '~providers~aws', 735 | hooks: {} 736 | }, 737 | { 738 | serverless: '~', 739 | provider: '~providers~aws', 740 | hooks: {} 741 | }, 742 | { 743 | serverless: '~', 744 | provider: '~providers~aws', 745 | hooks: {} 746 | }, 747 | { 748 | serverless: '~', 749 | options: '~providers~aws~options', 750 | provider: '~providers~aws', 751 | pkg: { 752 | serverless: '~', 753 | options: '~providers~aws~options', 754 | defaultExcludes: '~pluginManager~plugins~3~defaultExcludes', 755 | hooks: {} 756 | }, 757 | hooks: {} 758 | }, 759 | { 760 | serverless: '~', 761 | options: '~providers~aws~options', 762 | provider: '~providers~aws', 763 | hooks: {} 764 | }, 765 | { 766 | serverless: '~', 767 | options: '~providers~aws~options', 768 | provider: '~providers~aws', 769 | hooks: {} 770 | }, 771 | { 772 | sls: '~', 773 | package: {}, 774 | funcs: [], 775 | commands: { 776 | iopipe: { 777 | usage: 'Helps you start your first Serverless plugin', 778 | lifecycleEvents: ['run', 'finish'], 779 | options: { 780 | token: { 781 | usage: 782 | 'Your iopipe token (clientId) to wrap your functions with', 783 | required: false, 784 | shortcut: 't' 785 | }, 786 | noVerify: { 787 | usage: 788 | 'Skip a check that ensures iopipe is installed via npm/yarn and present in package.json', 789 | required: false, 790 | shortcut: 'nv' 791 | }, 792 | noUpgrade: { 793 | usage: 794 | 'The plugin automatically upgrades the IOpipe library to the most recent minor version. Use this option to disable that feature.', 795 | required: false, 796 | shortcut: 'nu' 797 | }, 798 | noYarn: { 799 | usage: 800 | 'When auto-upgrading, Yarn will be used in place of NPM if a yarn.lock file is found. Use this flag disable yarn and use NPM to upgrade the iopipe library.', 801 | required: false, 802 | shortcut: 'ny' 803 | }, 804 | exclude: { 805 | usage: 806 | 'Exclude certain handlers from being wrapped with IOpipe', 807 | required: false, 808 | shortcut: 'e' 809 | }, 810 | placeholder: { 811 | usage: 812 | 'Use process.env.IOPIPE_TOKEN as a placeholder variable to allow the token to be configured via environment variables in Serverless, AWS CLI, or AWS Console', 813 | required: false, 814 | shortcut: 'p' 815 | } 816 | } 817 | } 818 | }, 819 | hooks: {} 820 | } 821 | ], 822 | commands: { 823 | config: { 824 | usage: 'Configure Serverless', 825 | commands: { 826 | credentials: { 827 | usage: 828 | 'Configures a new provider profile for the Serverless Framework', 829 | lifecycleEvents: ['config'], 830 | options: { 831 | provider: { 832 | usage: 'Name of the provider. Supported providers: "aws"', 833 | required: true, 834 | shortcut: 'p' 835 | }, 836 | key: { 837 | usage: 'Access key for the provider', 838 | shortcut: 'k', 839 | required: true 840 | }, 841 | secret: { 842 | usage: 'Secret key for the provider', 843 | shortcut: 's', 844 | required: true 845 | }, 846 | profile: { 847 | usage: 848 | 'Name of the profile you wish to create. Defaults to "default"', 849 | shortcut: 'n' 850 | } 851 | }, 852 | key: 'config:credentials', 853 | pluginName: 'AwsConfigCredentials', 854 | commands: {} 855 | } 856 | }, 857 | key: 'config', 858 | pluginName: 'AwsConfigCredentials' 859 | }, 860 | create: { 861 | usage: 'Create new Serverless service', 862 | lifecycleEvents: ['create'], 863 | options: { 864 | template: { 865 | usage: 866 | 'Template for the service. Available templates: "aws-nodejs", "aws-python", "aws-groovy-gradle", "aws-java-maven", "aws-java-gradle", "aws-scala-sbt", "aws-csharp", "azure-nodejs", "openwhisk-nodejs" and "plugin"', 867 | required: true, 868 | shortcut: 't' 869 | }, 870 | path: { 871 | usage: 872 | 'The path where the service should be created (e.g. --path my-service)', 873 | shortcut: 'p' 874 | }, 875 | name: { 876 | usage: 877 | 'Name for the service. Overwrites the default name of the created service.', 878 | shortcut: 'n' 879 | } 880 | }, 881 | key: 'create', 882 | pluginName: 'Create', 883 | commands: {} 884 | }, 885 | install: { 886 | usage: 'Install a Serverless service from GitHub', 887 | lifecycleEvents: ['install'], 888 | options: { 889 | url: { 890 | usage: 'URL of the Serverless service on GitHub', 891 | required: true, 892 | shortcut: 'u' 893 | }, 894 | name: { 895 | usage: 'Name for the service', 896 | shortcut: 'n' 897 | } 898 | }, 899 | key: 'install', 900 | pluginName: 'Install', 901 | commands: {} 902 | }, 903 | deploy: { 904 | usage: 'Deploy a Serverless service', 905 | lifecycleEvents: [ 906 | 'cleanup', 907 | 'initialize', 908 | 'setupProviderConfiguration', 909 | 'createDeploymentArtifacts', 910 | 'compileFunctions', 911 | 'compileEvents', 912 | 'deploy' 913 | ], 914 | options: { 915 | stage: { 916 | usage: 'Stage of the service', 917 | shortcut: 's' 918 | }, 919 | region: { 920 | usage: 'Region of the service', 921 | shortcut: 'r' 922 | }, 923 | noDeploy: { 924 | usage: 'Build artifacts without deploying', 925 | shortcut: 'n' 926 | }, 927 | verbose: { 928 | usage: 'Show all stack events during deployment', 929 | shortcut: 'v' 930 | } 931 | }, 932 | commands: { 933 | function: { 934 | usage: 'Deploy a single function from the service', 935 | lifecycleEvents: ['initialize', 'packageFunction', 'deploy'], 936 | options: { 937 | function: { 938 | usage: 'Name of the function', 939 | shortcut: 'f', 940 | required: true 941 | }, 942 | stage: { 943 | usage: 'Stage of the function', 944 | shortcut: 's' 945 | }, 946 | region: { 947 | usage: 'Region of the function', 948 | shortcut: 'r' 949 | } 950 | }, 951 | key: 'deploy:function', 952 | pluginName: 'Deploy', 953 | commands: {} 954 | }, 955 | list: { 956 | usage: 'List deployed version of your Serverless Service', 957 | lifecycleEvents: ['log'], 958 | key: 'deploy:list', 959 | pluginName: 'Deploy', 960 | commands: {} 961 | } 962 | }, 963 | key: 'deploy', 964 | pluginName: 'Deploy' 965 | }, 966 | invoke: { 967 | usage: 'Invoke a deployed function', 968 | lifecycleEvents: ['invoke'], 969 | options: { 970 | function: { 971 | usage: 'The function name', 972 | required: true, 973 | shortcut: 'f' 974 | }, 975 | stage: { 976 | usage: 'Stage of the service', 977 | shortcut: 's' 978 | }, 979 | region: { 980 | usage: 'Region of the service', 981 | shortcut: 'r' 982 | }, 983 | path: { 984 | usage: 'Path to JSON or YAML file holding input data', 985 | shortcut: 'p' 986 | }, 987 | type: { 988 | usage: 'Type of invocation', 989 | shortcut: 't' 990 | }, 991 | log: { 992 | usage: 'Trigger logging data output', 993 | shortcut: 'l' 994 | }, 995 | data: { 996 | usage: 'input data', 997 | shortcut: 'd' 998 | } 999 | }, 1000 | commands: { 1001 | local: { 1002 | usage: 'Invoke function locally', 1003 | lifecycleEvents: ['invoke'], 1004 | options: { 1005 | function: { 1006 | usage: 'Name of the function', 1007 | shortcut: 'f', 1008 | required: true 1009 | }, 1010 | path: { 1011 | usage: 'Path to JSON or YAML file holding input data', 1012 | shortcut: 'p' 1013 | }, 1014 | data: { 1015 | usage: 'input data', 1016 | shortcut: 'd' 1017 | } 1018 | }, 1019 | key: 'invoke:local', 1020 | pluginName: 'Invoke', 1021 | commands: {} 1022 | } 1023 | }, 1024 | key: 'invoke', 1025 | pluginName: 'Invoke' 1026 | }, 1027 | info: { 1028 | usage: 'Display information about the service', 1029 | lifecycleEvents: ['info'], 1030 | options: { 1031 | stage: { 1032 | usage: 'Stage of the service', 1033 | shortcut: 's' 1034 | }, 1035 | region: { 1036 | usage: 'Region of the service', 1037 | shortcut: 'r' 1038 | }, 1039 | verbose: { 1040 | usage: 'Display Stack output', 1041 | shortcut: 'v' 1042 | } 1043 | }, 1044 | key: 'info', 1045 | pluginName: 'Info', 1046 | commands: {} 1047 | }, 1048 | logs: { 1049 | usage: 'Output the logs of a deployed function', 1050 | lifecycleEvents: ['logs'], 1051 | options: { 1052 | function: { 1053 | usage: 'The function name', 1054 | required: true, 1055 | shortcut: 'f' 1056 | }, 1057 | stage: { 1058 | usage: 'Stage of the service', 1059 | shortcut: 's' 1060 | }, 1061 | region: { 1062 | usage: 'Region of the service', 1063 | shortcut: 'r' 1064 | }, 1065 | tail: { 1066 | usage: 'Tail the log output', 1067 | shortcut: 't' 1068 | }, 1069 | startTime: { 1070 | usage: 'Logs before this time will not be displayed' 1071 | }, 1072 | filter: { 1073 | usage: 'A filter pattern' 1074 | }, 1075 | interval: { 1076 | usage: 'Tail polling interval in milliseconds. Default: `1000`', 1077 | shortcut: 'i' 1078 | } 1079 | }, 1080 | key: 'logs', 1081 | pluginName: 'Logs', 1082 | commands: {} 1083 | }, 1084 | metrics: { 1085 | usage: 'Show metrics for a specific function', 1086 | lifecycleEvents: ['metrics'], 1087 | options: { 1088 | function: { 1089 | usage: 'The function name', 1090 | shortcut: 'f' 1091 | }, 1092 | stage: { 1093 | usage: 'Stage of the service', 1094 | shortcut: 's' 1095 | }, 1096 | region: { 1097 | usage: 'Region of the service', 1098 | shortcut: 'r' 1099 | }, 1100 | startTime: { 1101 | usage: 'Start time for the metrics retrieval (e.g. 1970-01-01)' 1102 | }, 1103 | endTime: { 1104 | usage: 'End time for the metrics retrieval (e.g. 1970-01-01)' 1105 | } 1106 | }, 1107 | key: 'metrics', 1108 | pluginName: 'Metrics', 1109 | commands: {} 1110 | }, 1111 | remove: { 1112 | usage: 'Remove Serverless service and all resources', 1113 | lifecycleEvents: ['remove'], 1114 | options: { 1115 | stage: { 1116 | usage: 'Stage of the service', 1117 | shortcut: 's' 1118 | }, 1119 | region: { 1120 | usage: 'Region of the service', 1121 | shortcut: 'r' 1122 | }, 1123 | verbose: { 1124 | usage: 'Show all stack events during deployment', 1125 | shortcut: 'v' 1126 | } 1127 | }, 1128 | key: 'remove', 1129 | pluginName: 'Remove', 1130 | commands: {} 1131 | }, 1132 | rollback: { 1133 | usage: 'Rollback the Serverless service to a specific deployment', 1134 | lifecycleEvents: ['initialize', 'rollback'], 1135 | options: { 1136 | timestamp: { 1137 | usage: 1138 | 'Timestamp of the deployment (list deployments with `serverless deploy list`)', 1139 | shortcut: 't', 1140 | required: true 1141 | }, 1142 | verbose: { 1143 | usage: 'Show all stack events during deployment', 1144 | shortcut: 'v' 1145 | } 1146 | }, 1147 | key: 'rollback', 1148 | pluginName: 'Rollback', 1149 | commands: {} 1150 | }, 1151 | slstats: { 1152 | usage: 'Enable or disable stats', 1153 | lifecycleEvents: ['slstats'], 1154 | options: { 1155 | enable: { 1156 | usage: 'Enable stats ("--enable")', 1157 | shortcut: 'e' 1158 | }, 1159 | disable: { 1160 | usage: 'Disable stats ("--disable")', 1161 | shortcut: 'd' 1162 | } 1163 | }, 1164 | key: 'slstats', 1165 | pluginName: 'SlStats', 1166 | commands: {} 1167 | }, 1168 | iopipe: { 1169 | usage: 1170 | "Automatically wraps your function handlers in IOpipe, so you don't have to.", 1171 | lifecycleEvents: ['run', 'finish'], 1172 | options: { 1173 | token: { 1174 | usage: 'Your iopipe token (clientId) to wrap your functions with', 1175 | required: false, 1176 | shortcut: 't' 1177 | }, 1178 | noVerify: { 1179 | usage: 1180 | 'Skip a check that ensures iopipe is installed via npm/yarn and present in package.json', 1181 | required: false, 1182 | shortcut: 'nv' 1183 | }, 1184 | noUpgrade: { 1185 | usage: 1186 | 'The plugin automatically upgrades the IOpipe library to the most recent minor version. Use this option to disable that feature.', 1187 | required: false, 1188 | shortcut: 'nu' 1189 | }, 1190 | noYarn: { 1191 | usage: 1192 | 'When auto-upgrading, Yarn will be used in place of NPM if a yarn.lock file is found. Use this flag disable yarn and use NPM to upgrade the iopipe library.', 1193 | required: false, 1194 | shortcut: 'ny' 1195 | }, 1196 | exclude: { 1197 | usage: 'Exclude certain handlers from being wrapped with IOpipe', 1198 | required: false, 1199 | shortcut: 'e' 1200 | }, 1201 | placeholder: { 1202 | usage: 1203 | 'Use process.env.IOPIPE_TOKEN as a placeholder variable to allow the token to be configured via environment variables in Serverless, AWS CLI, or AWS Console', 1204 | required: false, 1205 | shortcut: 'p' 1206 | } 1207 | }, 1208 | key: 'iopipe', 1209 | pluginName: 'ServerlessIOpipePlugin', 1210 | commands: {} 1211 | } 1212 | }, 1213 | hooks: { 1214 | 'before:config:credentials:config': [ 1215 | { 1216 | pluginName: 'Config' 1217 | } 1218 | ], 1219 | 'create:create': [ 1220 | { 1221 | pluginName: 'Create' 1222 | } 1223 | ], 1224 | 'install:install': [ 1225 | { 1226 | pluginName: 'Install' 1227 | } 1228 | ], 1229 | 'deploy:cleanup': [ 1230 | { 1231 | pluginName: 'Package' 1232 | } 1233 | ], 1234 | 'deploy:createDeploymentArtifacts': [ 1235 | { 1236 | pluginName: 'Package' 1237 | } 1238 | ], 1239 | 'slstats:slstats': [ 1240 | { 1241 | pluginName: 'SlStats' 1242 | } 1243 | ], 1244 | 'config:credentials:config': [ 1245 | { 1246 | pluginName: 'AwsConfigCredentials' 1247 | } 1248 | ], 1249 | 'before:deploy:initialize': [ 1250 | { 1251 | pluginName: 'AwsDeploy' 1252 | } 1253 | ], 1254 | 'deploy:initialize': [ 1255 | { 1256 | pluginName: 'AwsDeploy' 1257 | } 1258 | ], 1259 | 'deploy:setupProviderConfiguration': [ 1260 | { 1261 | pluginName: 'AwsDeploy' 1262 | } 1263 | ], 1264 | 'before:deploy:compileFunctions': [ 1265 | { 1266 | pluginName: 'AwsDeploy' 1267 | } 1268 | ], 1269 | 'deploy:deploy': [ 1270 | { 1271 | pluginName: 'AwsDeploy' 1272 | }, 1273 | { 1274 | pluginName: 'AwsInfo' 1275 | } 1276 | ], 1277 | 'invoke:invoke': [ 1278 | { 1279 | pluginName: 'AwsInvoke' 1280 | } 1281 | ], 1282 | 'info:info': [ 1283 | { 1284 | pluginName: 'AwsInfo' 1285 | } 1286 | ], 1287 | 'logs:logs': [ 1288 | { 1289 | pluginName: 'AwsLogs' 1290 | } 1291 | ], 1292 | 'metrics:metrics': [ 1293 | { 1294 | pluginName: 'AwsMetrics' 1295 | } 1296 | ], 1297 | 'remove:remove': [ 1298 | { 1299 | pluginName: 'AwsRemove' 1300 | } 1301 | ], 1302 | 'before:rollback:initialize': [ 1303 | { 1304 | pluginName: 'AwsRollback' 1305 | } 1306 | ], 1307 | 'rollback:rollback': [ 1308 | { 1309 | pluginName: 'AwsRollback' 1310 | } 1311 | ], 1312 | 'deploy:compileFunctions': [ 1313 | { 1314 | pluginName: 'AwsCompileFunctions' 1315 | } 1316 | ], 1317 | 'deploy:compileEvents': [ 1318 | { 1319 | pluginName: 'AwsCompileScheduledEvents' 1320 | }, 1321 | { 1322 | pluginName: 'AwsCompileS3Events' 1323 | }, 1324 | { 1325 | pluginName: 'AwsCompileApigEvents' 1326 | }, 1327 | { 1328 | pluginName: 'AwsCompileSNSEvents' 1329 | }, 1330 | { 1331 | pluginName: 'AwsCompileStreamEvents' 1332 | }, 1333 | { 1334 | pluginName: 'AwsCompileAlexaSkillEvents' 1335 | }, 1336 | { 1337 | pluginName: 'AwsCompileIoTEvents' 1338 | }, 1339 | { 1340 | pluginName: 'AwsCompileCloudWatchEventEvents' 1341 | } 1342 | ], 1343 | 'deploy:function:initialize': [ 1344 | { 1345 | pluginName: 'AwsDeployFunction' 1346 | } 1347 | ], 1348 | 'deploy:function:packageFunction': [ 1349 | { 1350 | pluginName: 'AwsDeployFunction' 1351 | } 1352 | ], 1353 | 'deploy:function:deploy': [ 1354 | { 1355 | pluginName: 'AwsDeployFunction' 1356 | } 1357 | ], 1358 | 'before:deploy:list:log': [ 1359 | { 1360 | pluginName: 'AwsDeployList' 1361 | } 1362 | ], 1363 | 'deploy:list:log': [ 1364 | { 1365 | pluginName: 'AwsDeployList' 1366 | } 1367 | ], 1368 | 'invoke:local:invoke': [ 1369 | { 1370 | pluginName: 'AwsInvokeLocal' 1371 | } 1372 | ], 1373 | 'before:deploy:createDeploymentArtifacts': [ 1374 | { 1375 | pluginName: 'ServerlessIOpipePlugin' 1376 | } 1377 | ], 1378 | 'after:deploy:compileFunctions': [ 1379 | { 1380 | pluginName: 'ServerlessIOpipePlugin' 1381 | } 1382 | ], 1383 | 'iopipe:run': [ 1384 | { 1385 | pluginName: 'ServerlessIOpipePlugin' 1386 | } 1387 | ], 1388 | 'iopipe:finish': [ 1389 | { 1390 | pluginName: 'ServerlessIOpipePlugin' 1391 | } 1392 | ] 1393 | } 1394 | }, 1395 | config: { 1396 | serverless: '~', 1397 | serverlessPath: `${ 1398 | process.env.npm_config_prefix 1399 | }/node_modules/serverless/lib`, 1400 | interactive: true, 1401 | servicePath: path.resolve(__dirname, '../../testProjects/default') 1402 | }, 1403 | classes: {}, 1404 | cli: { 1405 | serverless: '~', 1406 | inputArray: null, 1407 | loadedPlugins: '~pluginManager~plugins', 1408 | loadedCommands: '~pluginManager~commands' 1409 | }, 1410 | processedInput: { 1411 | commands: '~pluginManager~cliCommands', 1412 | options: '~providers~aws~options' 1413 | } 1414 | }; 1415 | -------------------------------------------------------------------------------- /example/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@serverless/fdk@^0.5.1": 6 | version "0.5.1" 7 | resolved "https://registry.yarnpkg.com/@serverless/fdk/-/fdk-0.5.1.tgz#9d420568bfb291d73f8a8a9b35ba68a974f7d0b7" 8 | dependencies: 9 | isomorphic-fetch "^2.2.1" 10 | ramda "^0.24.1" 11 | url-parse "^1.1.9" 12 | 13 | "@types/graphql@0.10.2": 14 | version "0.10.2" 15 | resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.10.2.tgz#d7c79acbaa17453b6681c80c34b38fcb10c4c08c" 16 | 17 | agent-base@2: 18 | version "2.1.1" 19 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.1.1.tgz#d6de10d5af6132d5bd692427d46fc538539094c7" 20 | dependencies: 21 | extend "~3.0.0" 22 | semver "~5.0.1" 23 | 24 | ansi-escapes@^1.1.0: 25 | version "1.4.0" 26 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" 27 | 28 | ansi-regex@^2.0.0: 29 | version "2.1.1" 30 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 31 | 32 | ansi-styles@^2.2.1: 33 | version "2.2.1" 34 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 35 | 36 | ansi-styles@^3.1.0: 37 | version "3.2.0" 38 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" 39 | dependencies: 40 | color-convert "^1.9.0" 41 | 42 | ansi@^0.3.0, ansi@~0.3.1: 43 | version "0.3.1" 44 | resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" 45 | 46 | apollo-client@^1.9.2: 47 | version "1.9.3" 48 | resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-1.9.3.tgz#37000b3c801f4571b7b089739e696a158896aeab" 49 | dependencies: 50 | apollo-link-core "^0.5.0" 51 | graphql "^0.10.0" 52 | graphql-anywhere "^3.0.1" 53 | graphql-tag "^2.0.0" 54 | redux "^3.4.0" 55 | symbol-observable "^1.0.2" 56 | whatwg-fetch "^2.0.0" 57 | optionalDependencies: 58 | "@types/graphql" "0.10.2" 59 | 60 | apollo-link-core@^0.5.0: 61 | version "0.5.4" 62 | resolved "https://registry.yarnpkg.com/apollo-link-core/-/apollo-link-core-0.5.4.tgz#8efd4cd747959872a32f313f0ccfc2a76b396668" 63 | dependencies: 64 | graphql "^0.10.3" 65 | graphql-tag "^2.4.2" 66 | zen-observable-ts "^0.4.4" 67 | 68 | archiver-utils@^1.3.0: 69 | version "1.3.0" 70 | resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-1.3.0.tgz#e50b4c09c70bf3d680e32ff1b7994e9f9d895174" 71 | dependencies: 72 | glob "^7.0.0" 73 | graceful-fs "^4.1.0" 74 | lazystream "^1.0.0" 75 | lodash "^4.8.0" 76 | normalize-path "^2.0.0" 77 | readable-stream "^2.0.0" 78 | 79 | archiver@^1.1.0: 80 | version "1.3.0" 81 | resolved "https://registry.yarnpkg.com/archiver/-/archiver-1.3.0.tgz#4f2194d6d8f99df3f531e6881f14f15d55faaf22" 82 | dependencies: 83 | archiver-utils "^1.3.0" 84 | async "^2.0.0" 85 | buffer-crc32 "^0.2.1" 86 | glob "^7.0.0" 87 | lodash "^4.8.0" 88 | readable-stream "^2.0.0" 89 | tar-stream "^1.5.0" 90 | walkdir "^0.0.11" 91 | zip-stream "^1.1.0" 92 | 93 | are-we-there-yet@~1.1.2: 94 | version "1.1.4" 95 | resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" 96 | dependencies: 97 | delegates "^1.0.0" 98 | readable-stream "^2.0.6" 99 | 100 | argparse@^1.0.7: 101 | version "1.0.9" 102 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" 103 | dependencies: 104 | sprintf-js "~1.0.2" 105 | 106 | array-union@^1.0.1: 107 | version "1.0.2" 108 | resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" 109 | dependencies: 110 | array-uniq "^1.0.1" 111 | 112 | array-uniq@^1.0.1: 113 | version "1.0.3" 114 | resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" 115 | 116 | async@^1.5.2: 117 | version "1.5.2" 118 | resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" 119 | 120 | async@^2.0.0: 121 | version "2.5.0" 122 | resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d" 123 | dependencies: 124 | lodash "^4.14.0" 125 | 126 | asynckit@^0.4.0: 127 | version "0.4.0" 128 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 129 | 130 | aws-sdk@^2.75.0: 131 | version "2.141.0" 132 | resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.141.0.tgz#3d96a5970fd9f540ceabcc1d4baeb33b71583aa7" 133 | dependencies: 134 | buffer "4.9.1" 135 | crypto-browserify "1.0.9" 136 | events "^1.1.1" 137 | jmespath "0.15.0" 138 | querystring "0.2.0" 139 | sax "1.2.1" 140 | url "0.10.3" 141 | uuid "3.1.0" 142 | xml2js "0.4.17" 143 | xmlbuilder "4.2.1" 144 | 145 | balanced-match@^1.0.0: 146 | version "1.0.0" 147 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 148 | 149 | base64-js@0.0.8: 150 | version "0.0.8" 151 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" 152 | 153 | base64-js@^1.0.2: 154 | version "1.2.1" 155 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" 156 | 157 | bl@^1.0.0: 158 | version "1.2.1" 159 | resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" 160 | dependencies: 161 | readable-stream "^2.0.5" 162 | 163 | bluebird@^3.4.0: 164 | version "3.5.1" 165 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" 166 | 167 | brace-expansion@^1.1.7: 168 | version "1.1.8" 169 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" 170 | dependencies: 171 | balanced-match "^1.0.0" 172 | concat-map "0.0.1" 173 | 174 | buffer-crc32@^0.2.1, buffer-crc32@~0.2.3: 175 | version "0.2.13" 176 | resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" 177 | 178 | buffer@4.9.1: 179 | version "4.9.1" 180 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" 181 | dependencies: 182 | base64-js "^1.0.2" 183 | ieee754 "^1.1.4" 184 | isarray "^1.0.0" 185 | 186 | buffer@^3.0.1: 187 | version "3.6.0" 188 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" 189 | dependencies: 190 | base64-js "0.0.8" 191 | ieee754 "^1.1.4" 192 | isarray "^1.0.0" 193 | 194 | capture-stack-trace@^1.0.0: 195 | version "1.0.0" 196 | resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" 197 | 198 | caw@^2.0.0: 199 | version "2.0.1" 200 | resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" 201 | dependencies: 202 | get-proxy "^2.0.0" 203 | isurl "^1.0.0-alpha5" 204 | tunnel-agent "^0.6.0" 205 | url-to-options "^1.0.1" 206 | 207 | chalk@^1.0.0: 208 | version "1.1.3" 209 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 210 | dependencies: 211 | ansi-styles "^2.2.1" 212 | escape-string-regexp "^1.0.2" 213 | has-ansi "^2.0.0" 214 | strip-ansi "^3.0.0" 215 | supports-color "^2.0.0" 216 | 217 | chalk@^2.0.0: 218 | version "2.3.0" 219 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" 220 | dependencies: 221 | ansi-styles "^3.1.0" 222 | escape-string-regexp "^1.0.5" 223 | supports-color "^4.0.0" 224 | 225 | ci-info@^1.1.1: 226 | version "1.1.1" 227 | resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.1.tgz#47b44df118c48d2597b56d342e7e25791060171a" 228 | 229 | cli-cursor@^1.0.1: 230 | version "1.0.2" 231 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" 232 | dependencies: 233 | restore-cursor "^1.0.1" 234 | 235 | cli-width@^2.0.0: 236 | version "2.2.0" 237 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" 238 | 239 | code-point-at@^1.0.0: 240 | version "1.1.0" 241 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 242 | 243 | color-convert@^1.9.0: 244 | version "1.9.0" 245 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" 246 | dependencies: 247 | color-name "^1.1.1" 248 | 249 | color-name@^1.1.1: 250 | version "1.1.3" 251 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 252 | 253 | combined-stream@^1.0.5: 254 | version "1.0.5" 255 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" 256 | dependencies: 257 | delayed-stream "~1.0.0" 258 | 259 | commander@^2.9.0: 260 | version "2.11.0" 261 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" 262 | 263 | commander@~2.8.1: 264 | version "2.8.1" 265 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" 266 | dependencies: 267 | graceful-readlink ">= 1.0.0" 268 | 269 | component-emitter@^1.2.0: 270 | version "1.2.1" 271 | resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" 272 | 273 | compress-commons@^1.2.0: 274 | version "1.2.2" 275 | resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.2.2.tgz#524a9f10903f3a813389b0225d27c48bb751890f" 276 | dependencies: 277 | buffer-crc32 "^0.2.1" 278 | crc32-stream "^2.0.0" 279 | normalize-path "^2.0.0" 280 | readable-stream "^2.0.0" 281 | 282 | concat-map@0.0.1: 283 | version "0.0.1" 284 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 285 | 286 | concat-stream@^1.4.7: 287 | version "1.6.0" 288 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" 289 | dependencies: 290 | inherits "^2.0.3" 291 | readable-stream "^2.2.2" 292 | typedarray "^0.0.6" 293 | 294 | config-chain@^1.1.11: 295 | version "1.1.11" 296 | resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" 297 | dependencies: 298 | ini "^1.3.4" 299 | proto-list "~1.2.1" 300 | 301 | cookie@0.3.1: 302 | version "0.3.1" 303 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" 304 | 305 | cookiejar@^2.1.0: 306 | version "2.1.1" 307 | resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.1.tgz#41ad57b1b555951ec171412a81942b1e8200d34a" 308 | 309 | core-util-is@~1.0.0: 310 | version "1.0.2" 311 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 312 | 313 | crc32-stream@^2.0.0: 314 | version "2.0.0" 315 | resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-2.0.0.tgz#e3cdd3b4df3168dd74e3de3fbbcb7b297fe908f4" 316 | dependencies: 317 | crc "^3.4.4" 318 | readable-stream "^2.0.0" 319 | 320 | crc@^3.4.4: 321 | version "3.5.0" 322 | resolved "https://registry.yarnpkg.com/crc/-/crc-3.5.0.tgz#98b8ba7d489665ba3979f59b21381374101a1964" 323 | 324 | create-error-class@^3.0.0: 325 | version "3.0.2" 326 | resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" 327 | dependencies: 328 | capture-stack-trace "^1.0.0" 329 | 330 | crypto-browserify@1.0.9: 331 | version "1.0.9" 332 | resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-1.0.9.tgz#cc5449685dfb85eb11c9828acc7cb87ab5bbfcc0" 333 | 334 | debug@2, debug@^2.2.0: 335 | version "2.6.9" 336 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 337 | dependencies: 338 | ms "2.0.0" 339 | 340 | debug@^3.1.0: 341 | version "3.1.0" 342 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 343 | dependencies: 344 | ms "2.0.0" 345 | 346 | decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: 347 | version "4.1.1" 348 | resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" 349 | dependencies: 350 | file-type "^5.2.0" 351 | is-stream "^1.1.0" 352 | tar-stream "^1.5.2" 353 | 354 | decompress-tarbz2@^4.0.0: 355 | version "4.1.1" 356 | resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" 357 | dependencies: 358 | decompress-tar "^4.1.0" 359 | file-type "^6.1.0" 360 | is-stream "^1.1.0" 361 | seek-bzip "^1.0.5" 362 | unbzip2-stream "^1.0.9" 363 | 364 | decompress-targz@^4.0.0: 365 | version "4.1.1" 366 | resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" 367 | dependencies: 368 | decompress-tar "^4.1.1" 369 | file-type "^5.2.0" 370 | is-stream "^1.1.0" 371 | 372 | decompress-unzip@^4.0.1: 373 | version "4.0.1" 374 | resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" 375 | dependencies: 376 | file-type "^3.8.0" 377 | get-stream "^2.2.0" 378 | pify "^2.3.0" 379 | yauzl "^2.4.2" 380 | 381 | decompress@^4.0.0: 382 | version "4.2.0" 383 | resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" 384 | dependencies: 385 | decompress-tar "^4.0.0" 386 | decompress-tarbz2 "^4.0.0" 387 | decompress-targz "^4.0.0" 388 | decompress-unzip "^4.0.1" 389 | graceful-fs "^4.1.10" 390 | make-dir "^1.0.0" 391 | pify "^2.3.0" 392 | strip-dirs "^2.0.0" 393 | 394 | deep-extend@~0.4.0: 395 | version "0.4.2" 396 | resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" 397 | 398 | delayed-stream@~1.0.0: 399 | version "1.0.0" 400 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 401 | 402 | delegates@^1.0.0: 403 | version "1.0.0" 404 | resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" 405 | 406 | download@^5.0.2: 407 | version "5.0.3" 408 | resolved "https://registry.yarnpkg.com/download/-/download-5.0.3.tgz#63537f977f99266a30eb8a2a2fbd1f20b8000f7a" 409 | dependencies: 410 | caw "^2.0.0" 411 | decompress "^4.0.0" 412 | filenamify "^2.0.0" 413 | get-stream "^3.0.0" 414 | got "^6.3.0" 415 | mkdirp "^0.5.1" 416 | pify "^2.3.0" 417 | 418 | duplexer3@^0.1.4: 419 | version "0.1.4" 420 | resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" 421 | 422 | encoding@^0.1.11: 423 | version "0.1.12" 424 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" 425 | dependencies: 426 | iconv-lite "~0.4.13" 427 | 428 | end-of-stream@^1.0.0: 429 | version "1.4.0" 430 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" 431 | dependencies: 432 | once "^1.4.0" 433 | 434 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 435 | version "1.0.5" 436 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 437 | 438 | esprima@^4.0.0: 439 | version "4.0.0" 440 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" 441 | 442 | events@^1.1.1: 443 | version "1.1.1" 444 | resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" 445 | 446 | exit-hook@^1.0.0: 447 | version "1.1.1" 448 | resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" 449 | 450 | extend@3, extend@^3.0.0, extend@~3.0.0: 451 | version "3.0.1" 452 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" 453 | 454 | external-editor@^1.1.0: 455 | version "1.1.1" 456 | resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-1.1.1.tgz#12d7b0db850f7ff7e7081baf4005700060c4600b" 457 | dependencies: 458 | extend "^3.0.0" 459 | spawn-sync "^1.0.15" 460 | tmp "^0.0.29" 461 | 462 | fd-slicer@~1.0.1: 463 | version "1.0.1" 464 | resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" 465 | dependencies: 466 | pend "~1.2.0" 467 | 468 | figures@^1.3.5: 469 | version "1.7.0" 470 | resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" 471 | dependencies: 472 | escape-string-regexp "^1.0.5" 473 | object-assign "^4.1.0" 474 | 475 | file-type@^3.8.0: 476 | version "3.9.0" 477 | resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" 478 | 479 | file-type@^5.2.0: 480 | version "5.2.0" 481 | resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" 482 | 483 | file-type@^6.1.0: 484 | version "6.2.0" 485 | resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" 486 | 487 | filename-reserved-regex@^2.0.0: 488 | version "2.0.0" 489 | resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" 490 | 491 | filenamify@^2.0.0: 492 | version "2.0.0" 493 | resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-2.0.0.tgz#bd162262c0b6e94bfbcdcf19a3bbb3764f785695" 494 | dependencies: 495 | filename-reserved-regex "^2.0.0" 496 | strip-outer "^1.0.0" 497 | trim-repeated "^1.0.0" 498 | 499 | filesize@^3.3.0: 500 | version "3.5.11" 501 | resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.5.11.tgz#1919326749433bb3cf77368bd158caabcc19e9ee" 502 | 503 | form-data@^2.3.1: 504 | version "2.3.1" 505 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" 506 | dependencies: 507 | asynckit "^0.4.0" 508 | combined-stream "^1.0.5" 509 | mime-types "^2.1.12" 510 | 511 | formidable@^1.1.1: 512 | version "1.1.1" 513 | resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.1.1.tgz#96b8886f7c3c3508b932d6bd70c4d3a88f35f1a9" 514 | 515 | fs-extra@^0.26.7: 516 | version "0.26.7" 517 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.26.7.tgz#9ae1fdd94897798edab76d0918cf42d0c3184fa9" 518 | dependencies: 519 | graceful-fs "^4.1.2" 520 | jsonfile "^2.1.0" 521 | klaw "^1.0.0" 522 | path-is-absolute "^1.0.0" 523 | rimraf "^2.2.8" 524 | 525 | fs.realpath@^1.0.0: 526 | version "1.0.0" 527 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 528 | 529 | gauge@~1.2.5: 530 | version "1.2.7" 531 | resolved "https://registry.yarnpkg.com/gauge/-/gauge-1.2.7.tgz#e9cec5483d3d4ee0ef44b60a7d99e4935e136d93" 532 | dependencies: 533 | ansi "^0.3.0" 534 | has-unicode "^2.0.0" 535 | lodash.pad "^4.1.0" 536 | lodash.padend "^4.1.0" 537 | lodash.padstart "^4.1.0" 538 | 539 | get-proxy@^2.0.0: 540 | version "2.1.0" 541 | resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" 542 | dependencies: 543 | npm-conf "^1.1.0" 544 | 545 | get-stdin@^5.0.1: 546 | version "5.0.1" 547 | resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" 548 | 549 | get-stream@^2.2.0: 550 | version "2.3.1" 551 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" 552 | dependencies: 553 | object-assign "^4.0.1" 554 | pinkie-promise "^2.0.0" 555 | 556 | get-stream@^3.0.0: 557 | version "3.0.0" 558 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" 559 | 560 | glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: 561 | version "7.1.2" 562 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 563 | dependencies: 564 | fs.realpath "^1.0.0" 565 | inflight "^1.0.4" 566 | inherits "2" 567 | minimatch "^3.0.4" 568 | once "^1.3.0" 569 | path-is-absolute "^1.0.0" 570 | 571 | globby@^6.1.0: 572 | version "6.1.0" 573 | resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" 574 | dependencies: 575 | array-union "^1.0.1" 576 | glob "^7.0.3" 577 | object-assign "^4.0.1" 578 | pify "^2.0.0" 579 | pinkie-promise "^2.0.0" 580 | 581 | got@^6.3.0: 582 | version "6.7.1" 583 | resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" 584 | dependencies: 585 | create-error-class "^3.0.0" 586 | duplexer3 "^0.1.4" 587 | get-stream "^3.0.0" 588 | is-redirect "^1.0.0" 589 | is-retry-allowed "^1.0.0" 590 | is-stream "^1.0.0" 591 | lowercase-keys "^1.0.0" 592 | safe-buffer "^5.0.1" 593 | timed-out "^4.0.0" 594 | unzip-response "^2.0.1" 595 | url-parse-lax "^1.0.0" 596 | 597 | graceful-fs@^4.1.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: 598 | version "4.1.11" 599 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" 600 | 601 | "graceful-readlink@>= 1.0.0": 602 | version "1.0.1" 603 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" 604 | 605 | graphlib@^2.1.1: 606 | version "2.1.1" 607 | resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.1.tgz#42352c52ba2f4d035cb566eb91f7395f76ebc951" 608 | dependencies: 609 | lodash "^4.11.1" 610 | 611 | graphql-anywhere@^3.0.1: 612 | version "3.1.0" 613 | resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-3.1.0.tgz#3ea0d8e8646b5cee68035016a9a7557c15c21e96" 614 | 615 | graphql-tag@^2.0.0, graphql-tag@^2.4.0, graphql-tag@^2.4.2: 616 | version "2.5.0" 617 | resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.5.0.tgz#b43bfd8b5babcd2c205ad680c03e98b238934e0f" 618 | 619 | graphql@^0.10.0, graphql@^0.10.1, graphql@^0.10.3: 620 | version "0.10.5" 621 | resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.10.5.tgz#c9be17ca2bdfdbd134077ffd9bbaa48b8becd298" 622 | dependencies: 623 | iterall "^1.1.0" 624 | 625 | has-ansi@^2.0.0: 626 | version "2.0.0" 627 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 628 | dependencies: 629 | ansi-regex "^2.0.0" 630 | 631 | has-flag@^2.0.0: 632 | version "2.0.0" 633 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" 634 | 635 | has-symbol-support-x@^1.4.1: 636 | version "1.4.1" 637 | resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.1.tgz#66ec2e377e0c7d7ccedb07a3a84d77510ff1bc4c" 638 | 639 | has-to-string-tag-x@^1.2.0: 640 | version "1.4.1" 641 | resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" 642 | dependencies: 643 | has-symbol-support-x "^1.4.1" 644 | 645 | has-unicode@^2.0.0: 646 | version "2.0.1" 647 | resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" 648 | 649 | https-proxy-agent@^1.0.0: 650 | version "1.0.0" 651 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz#35f7da6c48ce4ddbfa264891ac593ee5ff8671e6" 652 | dependencies: 653 | agent-base "2" 654 | debug "2" 655 | extend "3" 656 | 657 | iconv-lite@~0.4.13: 658 | version "0.4.19" 659 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" 660 | 661 | ieee754@^1.1.4: 662 | version "1.1.8" 663 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" 664 | 665 | imurmurhash@^0.1.4: 666 | version "0.1.4" 667 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 668 | 669 | inflight@^1.0.4: 670 | version "1.0.6" 671 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 672 | dependencies: 673 | once "^1.3.0" 674 | wrappy "1" 675 | 676 | inherits@2, inherits@^2.0.3, inherits@~2.0.3: 677 | version "2.0.3" 678 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 679 | 680 | ini@^1.3.4, ini@~1.3.0: 681 | version "1.3.4" 682 | resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" 683 | 684 | inquirer@^1.0.2: 685 | version "1.2.3" 686 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-1.2.3.tgz#4dec6f32f37ef7bb0b2ed3f1d1a5c3f545074918" 687 | dependencies: 688 | ansi-escapes "^1.1.0" 689 | chalk "^1.0.0" 690 | cli-cursor "^1.0.1" 691 | cli-width "^2.0.0" 692 | external-editor "^1.1.0" 693 | figures "^1.3.5" 694 | lodash "^4.3.0" 695 | mute-stream "0.0.6" 696 | pinkie-promise "^2.0.0" 697 | run-async "^2.2.0" 698 | rx "^4.1.0" 699 | string-width "^1.0.1" 700 | strip-ansi "^3.0.0" 701 | through "^2.3.6" 702 | 703 | iopipe@^1.1.0: 704 | version "1.1.0" 705 | resolved "https://registry.yarnpkg.com/iopipe/-/iopipe-1.1.0.tgz#f98bbb3f676089594f1f48bfc631c1ef41e496e2" 706 | 707 | is-docker@^1.1.0: 708 | version "1.1.0" 709 | resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-1.1.0.tgz#f04374d4eee5310e9a8e113bf1495411e46176a1" 710 | 711 | is-fullwidth-code-point@^1.0.0: 712 | version "1.0.0" 713 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 714 | dependencies: 715 | number-is-nan "^1.0.0" 716 | 717 | is-natural-number@^4.0.1: 718 | version "4.0.1" 719 | resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" 720 | 721 | is-object@^1.0.1: 722 | version "1.0.1" 723 | resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" 724 | 725 | is-promise@^2.1.0: 726 | version "2.1.0" 727 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" 728 | 729 | is-redirect@^1.0.0: 730 | version "1.0.0" 731 | resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" 732 | 733 | is-retry-allowed@^1.0.0: 734 | version "1.1.0" 735 | resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" 736 | 737 | is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: 738 | version "1.1.0" 739 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 740 | 741 | is-wsl@^1.1.0: 742 | version "1.1.0" 743 | resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" 744 | 745 | isarray@^1.0.0, isarray@~1.0.0: 746 | version "1.0.0" 747 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 748 | 749 | isomorphic-fetch@^2.2.1: 750 | version "2.2.1" 751 | resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" 752 | dependencies: 753 | node-fetch "^1.0.1" 754 | whatwg-fetch ">=0.10.0" 755 | 756 | isurl@^1.0.0-alpha5: 757 | version "1.0.0" 758 | resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" 759 | dependencies: 760 | has-to-string-tag-x "^1.2.0" 761 | is-object "^1.0.1" 762 | 763 | iterall@^1.1.0: 764 | version "1.1.3" 765 | resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.3.tgz#1cbbff96204056dde6656e2ed2e2226d0e6d72c9" 766 | 767 | jmespath@0.15.0: 768 | version "0.15.0" 769 | resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" 770 | 771 | js-tokens@^3.0.0: 772 | version "3.0.2" 773 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" 774 | 775 | js-yaml@^3.6.1, js-yaml@^3.8.3: 776 | version "3.10.0" 777 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" 778 | dependencies: 779 | argparse "^1.0.7" 780 | esprima "^4.0.0" 781 | 782 | json-refs@^2.1.5: 783 | version "2.1.7" 784 | resolved "https://registry.yarnpkg.com/json-refs/-/json-refs-2.1.7.tgz#b9eb01fe29f5ea3e92878f15aea10ad38b5acf89" 785 | dependencies: 786 | commander "^2.9.0" 787 | graphlib "^2.1.1" 788 | js-yaml "^3.8.3" 789 | native-promise-only "^0.8.1" 790 | path-loader "^1.0.2" 791 | slash "^1.0.0" 792 | uri-js "^3.0.2" 793 | 794 | json-stringify-safe@5.0.1: 795 | version "5.0.1" 796 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 797 | 798 | jsonfile@^2.1.0: 799 | version "2.4.0" 800 | resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" 801 | optionalDependencies: 802 | graceful-fs "^4.1.6" 803 | 804 | jwt-decode@^2.2.0: 805 | version "2.2.0" 806 | resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-2.2.0.tgz#7d86bd56679f58ce6a84704a657dd392bba81a79" 807 | 808 | klaw@^1.0.0: 809 | version "1.3.1" 810 | resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" 811 | optionalDependencies: 812 | graceful-fs "^4.1.9" 813 | 814 | lazystream@^1.0.0: 815 | version "1.0.0" 816 | resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" 817 | dependencies: 818 | readable-stream "^2.0.5" 819 | 820 | lodash-es@^4.2.1: 821 | version "4.17.4" 822 | resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7" 823 | 824 | lodash.difference@^4.5.0: 825 | version "4.5.0" 826 | resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c" 827 | 828 | lodash.pad@^4.1.0: 829 | version "4.5.1" 830 | resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70" 831 | 832 | lodash.padend@^4.1.0: 833 | version "4.6.1" 834 | resolved "https://registry.yarnpkg.com/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" 835 | 836 | lodash.padstart@^4.1.0: 837 | version "4.6.1" 838 | resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" 839 | 840 | lodash.uniq@^4.5.0: 841 | version "4.5.0" 842 | resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" 843 | 844 | lodash@^4.0.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.8.0: 845 | version "4.17.4" 846 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 847 | 848 | loose-envify@^1.1.0: 849 | version "1.3.1" 850 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" 851 | dependencies: 852 | js-tokens "^3.0.0" 853 | 854 | lowercase-keys@^1.0.0: 855 | version "1.0.0" 856 | resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" 857 | 858 | lsmod@1.0.0: 859 | version "1.0.0" 860 | resolved "https://registry.yarnpkg.com/lsmod/-/lsmod-1.0.0.tgz#9a00f76dca36eb23fa05350afe1b585d4299e64b" 861 | 862 | make-dir@^1.0.0: 863 | version "1.1.0" 864 | resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.1.0.tgz#19b4369fe48c116f53c2af95ad102c0e39e85d51" 865 | dependencies: 866 | pify "^3.0.0" 867 | 868 | methods@^1.1.1: 869 | version "1.1.2" 870 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 871 | 872 | mime-db@~1.30.0: 873 | version "1.30.0" 874 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" 875 | 876 | mime-types@^2.1.12: 877 | version "2.1.17" 878 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" 879 | dependencies: 880 | mime-db "~1.30.0" 881 | 882 | mime@^1.4.1: 883 | version "1.4.1" 884 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" 885 | 886 | minimatch@^3.0.4: 887 | version "3.0.4" 888 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 889 | dependencies: 890 | brace-expansion "^1.1.7" 891 | 892 | minimist@0.0.8: 893 | version "0.0.8" 894 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 895 | 896 | minimist@^1.2.0: 897 | version "1.2.0" 898 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" 899 | 900 | mkdirp@^0.5.1: 901 | version "0.5.1" 902 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 903 | dependencies: 904 | minimist "0.0.8" 905 | 906 | moment@^2.13.0: 907 | version "2.19.1" 908 | resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.1.tgz#56da1a2d1cbf01d38b7e1afc31c10bcfa1929167" 909 | 910 | ms@2.0.0: 911 | version "2.0.0" 912 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 913 | 914 | mute-stream@0.0.6: 915 | version "0.0.6" 916 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.6.tgz#48962b19e169fd1dfc240b3f1e7317627bbc47db" 917 | 918 | native-promise-only@^0.8.1: 919 | version "0.8.1" 920 | resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11" 921 | 922 | node-fetch@^1.0.1, node-fetch@^1.6.0: 923 | version "1.7.3" 924 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" 925 | dependencies: 926 | encoding "^0.1.11" 927 | is-stream "^1.0.1" 928 | 929 | node-forge@^0.7.1: 930 | version "0.7.1" 931 | resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.1.tgz#9da611ea08982f4b94206b3beb4cc9665f20c300" 932 | 933 | normalize-path@^2.0.0: 934 | version "2.1.1" 935 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" 936 | dependencies: 937 | remove-trailing-separator "^1.0.1" 938 | 939 | npm-conf@^1.1.0: 940 | version "1.1.2" 941 | resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.2.tgz#170a2c48a0c6ad0495f03f87aec2da11ef47a525" 942 | dependencies: 943 | config-chain "^1.1.11" 944 | pify "^3.0.0" 945 | 946 | npmlog@^2.0.3: 947 | version "2.0.4" 948 | resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-2.0.4.tgz#98b52530f2514ca90d09ec5b22c8846722375692" 949 | dependencies: 950 | ansi "~0.3.1" 951 | are-we-there-yet "~1.1.2" 952 | gauge "~1.2.5" 953 | 954 | number-is-nan@^1.0.0: 955 | version "1.0.1" 956 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 957 | 958 | object-assign@^4.0.1, object-assign@^4.1.0: 959 | version "4.1.1" 960 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 961 | 962 | once@^1.3.0, once@^1.4.0: 963 | version "1.4.0" 964 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 965 | dependencies: 966 | wrappy "1" 967 | 968 | onetime@^1.0.0: 969 | version "1.1.0" 970 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" 971 | 972 | opn@^5.0.0: 973 | version "5.1.0" 974 | resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519" 975 | dependencies: 976 | is-wsl "^1.1.0" 977 | 978 | os-shim@^0.1.2: 979 | version "0.1.3" 980 | resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" 981 | 982 | os-tmpdir@~1.0.1: 983 | version "1.0.2" 984 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 985 | 986 | path-is-absolute@^1.0.0: 987 | version "1.0.1" 988 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 989 | 990 | path-loader@^1.0.2: 991 | version "1.0.4" 992 | resolved "https://registry.yarnpkg.com/path-loader/-/path-loader-1.0.4.tgz#107dc8b1b7c0f6a8a18e7749bdaf46a26c2d98b4" 993 | dependencies: 994 | native-promise-only "^0.8.1" 995 | superagent "^3.6.3" 996 | 997 | pend@~1.2.0: 998 | version "1.2.0" 999 | resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" 1000 | 1001 | pify@^2.0.0, pify@^2.3.0: 1002 | version "2.3.0" 1003 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 1004 | 1005 | pify@^3.0.0: 1006 | version "3.0.0" 1007 | resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" 1008 | 1009 | pinkie-promise@^2.0.0: 1010 | version "2.0.1" 1011 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 1012 | dependencies: 1013 | pinkie "^2.0.0" 1014 | 1015 | pinkie@^2.0.0: 1016 | version "2.0.4" 1017 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 1018 | 1019 | prepend-http@^1.0.1: 1020 | version "1.0.4" 1021 | resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" 1022 | 1023 | process-nextick-args@~1.0.6: 1024 | version "1.0.7" 1025 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" 1026 | 1027 | proto-list@~1.2.1: 1028 | version "1.2.4" 1029 | resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" 1030 | 1031 | punycode@1.3.2: 1032 | version "1.3.2" 1033 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" 1034 | 1035 | punycode@^2.1.0: 1036 | version "2.1.0" 1037 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" 1038 | 1039 | qs@^6.5.1: 1040 | version "6.5.1" 1041 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" 1042 | 1043 | querystring@0.2.0: 1044 | version "0.2.0" 1045 | resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" 1046 | 1047 | querystringify@~1.0.0: 1048 | version "1.0.0" 1049 | resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" 1050 | 1051 | ramda@^0.24.1: 1052 | version "0.24.1" 1053 | resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857" 1054 | 1055 | raven@^1.2.1: 1056 | version "1.2.1" 1057 | resolved "https://registry.yarnpkg.com/raven/-/raven-1.2.1.tgz#949c134db028a190b7bbf8f790aae541b7c020bd" 1058 | dependencies: 1059 | cookie "0.3.1" 1060 | json-stringify-safe "5.0.1" 1061 | lsmod "1.0.0" 1062 | stack-trace "0.0.9" 1063 | uuid "3.0.0" 1064 | 1065 | rc@^1.1.6: 1066 | version "1.2.2" 1067 | resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.2.tgz#d8ce9cb57e8d64d9c7badd9876c7c34cbe3c7077" 1068 | dependencies: 1069 | deep-extend "~0.4.0" 1070 | ini "~1.3.0" 1071 | minimist "^1.2.0" 1072 | strip-json-comments "~2.0.1" 1073 | 1074 | readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2: 1075 | version "2.3.3" 1076 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" 1077 | dependencies: 1078 | core-util-is "~1.0.0" 1079 | inherits "~2.0.3" 1080 | isarray "~1.0.0" 1081 | process-nextick-args "~1.0.6" 1082 | safe-buffer "~5.1.1" 1083 | string_decoder "~1.0.3" 1084 | util-deprecate "~1.0.1" 1085 | 1086 | redux@^3.4.0: 1087 | version "3.7.2" 1088 | resolved "https://registry.yarnpkg.com/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b" 1089 | dependencies: 1090 | lodash "^4.2.1" 1091 | lodash-es "^4.2.1" 1092 | loose-envify "^1.1.0" 1093 | symbol-observable "^1.0.3" 1094 | 1095 | remove-trailing-separator@^1.0.1: 1096 | version "1.1.0" 1097 | resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" 1098 | 1099 | replaceall@^0.1.6: 1100 | version "0.1.6" 1101 | resolved "https://registry.yarnpkg.com/replaceall/-/replaceall-0.1.6.tgz#81d81ac7aeb72d7f5c4942adf2697a3220688d8e" 1102 | 1103 | requires-port@1.0.x: 1104 | version "1.0.0" 1105 | resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 1106 | 1107 | restore-cursor@^1.0.1: 1108 | version "1.0.1" 1109 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" 1110 | dependencies: 1111 | exit-hook "^1.0.0" 1112 | onetime "^1.0.0" 1113 | 1114 | rimraf@^2.2.8: 1115 | version "2.6.2" 1116 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" 1117 | dependencies: 1118 | glob "^7.0.5" 1119 | 1120 | run-async@^2.2.0: 1121 | version "2.3.0" 1122 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" 1123 | dependencies: 1124 | is-promise "^2.1.0" 1125 | 1126 | rx@^4.1.0: 1127 | version "4.1.0" 1128 | resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" 1129 | 1130 | safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: 1131 | version "5.1.1" 1132 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" 1133 | 1134 | sax@1.2.1: 1135 | version "1.2.1" 1136 | resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" 1137 | 1138 | sax@>=0.6.0: 1139 | version "1.2.4" 1140 | resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" 1141 | 1142 | seek-bzip@^1.0.5: 1143 | version "1.0.5" 1144 | resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" 1145 | dependencies: 1146 | commander "~2.8.1" 1147 | 1148 | semver-regex@^1.0.0: 1149 | version "1.0.0" 1150 | resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-1.0.0.tgz#92a4969065f9c70c694753d55248fc68f8f652c9" 1151 | 1152 | semver@^5.0.3: 1153 | version "5.4.1" 1154 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" 1155 | 1156 | semver@~5.0.1: 1157 | version "5.0.3" 1158 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" 1159 | 1160 | serverless-plugin-iopipe@^0.3.3: 1161 | version "0.3.3" 1162 | resolved "https://registry.yarnpkg.com/serverless-plugin-iopipe/-/serverless-plugin-iopipe-0.3.3.tgz#577f9591b963da007bc62decf2db51caa97e306c" 1163 | 1164 | serverless@^1.23.0: 1165 | version "1.23.0" 1166 | resolved "https://registry.yarnpkg.com/serverless/-/serverless-1.23.0.tgz#c4063f2ffee5748d2db0d02d585e7869fca80c34" 1167 | dependencies: 1168 | "@serverless/fdk" "^0.5.1" 1169 | apollo-client "^1.9.2" 1170 | archiver "^1.1.0" 1171 | async "^1.5.2" 1172 | aws-sdk "^2.75.0" 1173 | bluebird "^3.4.0" 1174 | chalk "^2.0.0" 1175 | ci-info "^1.1.1" 1176 | download "^5.0.2" 1177 | filesize "^3.3.0" 1178 | fs-extra "^0.26.7" 1179 | get-stdin "^5.0.1" 1180 | globby "^6.1.0" 1181 | graceful-fs "^4.1.11" 1182 | graphql "^0.10.1" 1183 | graphql-tag "^2.4.0" 1184 | https-proxy-agent "^1.0.0" 1185 | is-docker "^1.1.0" 1186 | js-yaml "^3.6.1" 1187 | json-refs "^2.1.5" 1188 | jwt-decode "^2.2.0" 1189 | lodash "^4.13.1" 1190 | minimist "^1.2.0" 1191 | moment "^2.13.0" 1192 | node-fetch "^1.6.0" 1193 | node-forge "^0.7.1" 1194 | opn "^5.0.0" 1195 | raven "^1.2.1" 1196 | rc "^1.1.6" 1197 | replaceall "^0.1.6" 1198 | semver "^5.0.3" 1199 | semver-regex "^1.0.0" 1200 | shelljs "^0.6.0" 1201 | tabtab "^2.2.2" 1202 | uuid "^2.0.2" 1203 | write-file-atomic "^2.1.0" 1204 | yaml-ast-parser "0.0.34" 1205 | 1206 | shelljs@^0.6.0: 1207 | version "0.6.1" 1208 | resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8" 1209 | 1210 | signal-exit@^3.0.2: 1211 | version "3.0.2" 1212 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 1213 | 1214 | slash@^1.0.0: 1215 | version "1.0.0" 1216 | resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" 1217 | 1218 | spawn-sync@^1.0.15: 1219 | version "1.0.15" 1220 | resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" 1221 | dependencies: 1222 | concat-stream "^1.4.7" 1223 | os-shim "^0.1.2" 1224 | 1225 | sprintf-js@~1.0.2: 1226 | version "1.0.3" 1227 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1228 | 1229 | stack-trace@0.0.9: 1230 | version "0.0.9" 1231 | resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695" 1232 | 1233 | string-width@^1.0.1: 1234 | version "1.0.2" 1235 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 1236 | dependencies: 1237 | code-point-at "^1.0.0" 1238 | is-fullwidth-code-point "^1.0.0" 1239 | strip-ansi "^3.0.0" 1240 | 1241 | string_decoder@~1.0.3: 1242 | version "1.0.3" 1243 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" 1244 | dependencies: 1245 | safe-buffer "~5.1.0" 1246 | 1247 | strip-ansi@^3.0.0: 1248 | version "3.0.1" 1249 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 1250 | dependencies: 1251 | ansi-regex "^2.0.0" 1252 | 1253 | strip-dirs@^2.0.0: 1254 | version "2.1.0" 1255 | resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" 1256 | dependencies: 1257 | is-natural-number "^4.0.1" 1258 | 1259 | strip-json-comments@~2.0.1: 1260 | version "2.0.1" 1261 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 1262 | 1263 | strip-outer@^1.0.0: 1264 | version "1.0.0" 1265 | resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.0.tgz#aac0ba60d2e90c5d4f275fd8869fd9a2d310ffb8" 1266 | dependencies: 1267 | escape-string-regexp "^1.0.2" 1268 | 1269 | superagent@^3.6.3: 1270 | version "3.8.0" 1271 | resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.8.0.tgz#87e3ed536c8860c08c7c7d1225da9a80cab064c6" 1272 | dependencies: 1273 | component-emitter "^1.2.0" 1274 | cookiejar "^2.1.0" 1275 | debug "^3.1.0" 1276 | extend "^3.0.0" 1277 | form-data "^2.3.1" 1278 | formidable "^1.1.1" 1279 | methods "^1.1.1" 1280 | mime "^1.4.1" 1281 | qs "^6.5.1" 1282 | readable-stream "^2.0.5" 1283 | 1284 | supports-color@^2.0.0: 1285 | version "2.0.0" 1286 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 1287 | 1288 | supports-color@^4.0.0: 1289 | version "4.5.0" 1290 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" 1291 | dependencies: 1292 | has-flag "^2.0.0" 1293 | 1294 | symbol-observable@^1.0.2, symbol-observable@^1.0.3: 1295 | version "1.0.4" 1296 | resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" 1297 | 1298 | tabtab@^2.2.2: 1299 | version "2.2.2" 1300 | resolved "https://registry.yarnpkg.com/tabtab/-/tabtab-2.2.2.tgz#7a047f143b010b4cbd31f857e82961512cbf4e14" 1301 | dependencies: 1302 | debug "^2.2.0" 1303 | inquirer "^1.0.2" 1304 | lodash.difference "^4.5.0" 1305 | lodash.uniq "^4.5.0" 1306 | minimist "^1.2.0" 1307 | mkdirp "^0.5.1" 1308 | npmlog "^2.0.3" 1309 | object-assign "^4.1.0" 1310 | 1311 | tar-stream@^1.5.0, tar-stream@^1.5.2: 1312 | version "1.5.4" 1313 | resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.4.tgz#36549cf04ed1aee9b2a30c0143252238daf94016" 1314 | dependencies: 1315 | bl "^1.0.0" 1316 | end-of-stream "^1.0.0" 1317 | readable-stream "^2.0.0" 1318 | xtend "^4.0.0" 1319 | 1320 | through@^2.3.6: 1321 | version "2.3.8" 1322 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 1323 | 1324 | timed-out@^4.0.0: 1325 | version "4.0.1" 1326 | resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" 1327 | 1328 | tmp@^0.0.29: 1329 | version "0.0.29" 1330 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0" 1331 | dependencies: 1332 | os-tmpdir "~1.0.1" 1333 | 1334 | trim-repeated@^1.0.0: 1335 | version "1.0.0" 1336 | resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" 1337 | dependencies: 1338 | escape-string-regexp "^1.0.2" 1339 | 1340 | tunnel-agent@^0.6.0: 1341 | version "0.6.0" 1342 | resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 1343 | dependencies: 1344 | safe-buffer "^5.0.1" 1345 | 1346 | typedarray@^0.0.6: 1347 | version "0.0.6" 1348 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 1349 | 1350 | unbzip2-stream@^1.0.9: 1351 | version "1.2.5" 1352 | resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz#73a033a567bbbde59654b193c44d48a7e4f43c47" 1353 | dependencies: 1354 | buffer "^3.0.1" 1355 | through "^2.3.6" 1356 | 1357 | unzip-response@^2.0.1: 1358 | version "2.0.1" 1359 | resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" 1360 | 1361 | uri-js@^3.0.2: 1362 | version "3.0.2" 1363 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-3.0.2.tgz#f90b858507f81dea4dcfbb3c4c3dbfa2b557faaa" 1364 | dependencies: 1365 | punycode "^2.1.0" 1366 | 1367 | url-parse-lax@^1.0.0: 1368 | version "1.0.0" 1369 | resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" 1370 | dependencies: 1371 | prepend-http "^1.0.1" 1372 | 1373 | url-parse@^1.1.9: 1374 | version "1.1.9" 1375 | resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.1.9.tgz#c67f1d775d51f0a18911dd7b3ffad27bb9e5bd19" 1376 | dependencies: 1377 | querystringify "~1.0.0" 1378 | requires-port "1.0.x" 1379 | 1380 | url-to-options@^1.0.1: 1381 | version "1.0.1" 1382 | resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" 1383 | 1384 | url@0.10.3: 1385 | version "0.10.3" 1386 | resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" 1387 | dependencies: 1388 | punycode "1.3.2" 1389 | querystring "0.2.0" 1390 | 1391 | util-deprecate@~1.0.1: 1392 | version "1.0.2" 1393 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1394 | 1395 | uuid@3.0.0: 1396 | version "3.0.0" 1397 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.0.tgz#6728fc0459c450d796a99c31837569bdf672d728" 1398 | 1399 | uuid@3.1.0: 1400 | version "3.1.0" 1401 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" 1402 | 1403 | uuid@^2.0.2: 1404 | version "2.0.3" 1405 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" 1406 | 1407 | walkdir@^0.0.11: 1408 | version "0.0.11" 1409 | resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.0.11.tgz#a16d025eb931bd03b52f308caed0f40fcebe9532" 1410 | 1411 | whatwg-fetch@>=0.10.0, whatwg-fetch@^2.0.0: 1412 | version "2.0.3" 1413 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" 1414 | 1415 | wrappy@1: 1416 | version "1.0.2" 1417 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1418 | 1419 | write-file-atomic@^2.1.0: 1420 | version "2.3.0" 1421 | resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" 1422 | dependencies: 1423 | graceful-fs "^4.1.11" 1424 | imurmurhash "^0.1.4" 1425 | signal-exit "^3.0.2" 1426 | 1427 | xml2js@0.4.17: 1428 | version "0.4.17" 1429 | resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.17.tgz#17be93eaae3f3b779359c795b419705a8817e868" 1430 | dependencies: 1431 | sax ">=0.6.0" 1432 | xmlbuilder "^4.1.0" 1433 | 1434 | xmlbuilder@4.2.1, xmlbuilder@^4.1.0: 1435 | version "4.2.1" 1436 | resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-4.2.1.tgz#aa58a3041a066f90eaa16c2f5389ff19f3f461a5" 1437 | dependencies: 1438 | lodash "^4.0.0" 1439 | 1440 | xtend@^4.0.0: 1441 | version "4.0.1" 1442 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" 1443 | 1444 | yaml-ast-parser@0.0.34: 1445 | version "0.0.34" 1446 | resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.34.tgz#d00f3cf9d773b7241409ae92a6740d1db19f49e6" 1447 | 1448 | yauzl@^2.4.2: 1449 | version "2.9.1" 1450 | resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.9.1.tgz#a81981ea70a57946133883f029c5821a89359a7f" 1451 | dependencies: 1452 | buffer-crc32 "~0.2.3" 1453 | fd-slicer "~1.0.1" 1454 | 1455 | zen-observable-ts@^0.4.4: 1456 | version "0.4.4" 1457 | resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.4.4.tgz#c244c71eaebef79a985ccf9895bc90307a6e9712" 1458 | 1459 | zip-stream@^1.1.0: 1460 | version "1.2.0" 1461 | resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04" 1462 | dependencies: 1463 | archiver-utils "^1.3.0" 1464 | compress-commons "^1.2.0" 1465 | lodash "^4.8.0" 1466 | readable-stream "^2.0.0" 1467 | --------------------------------------------------------------------------------