├── .circleci └── config.yml ├── .editorconfig ├── .env.sample ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .node-version ├── LICENSE ├── README.md ├── app ├── README.md ├── assets │ └── README.md ├── components │ ├── Logo.vue │ └── README.md ├── layouts │ ├── README.md │ ├── default.vue │ └── error.vue ├── middleware │ └── README.md ├── pages │ ├── README.md │ ├── about.vue │ └── index.vue ├── plugins │ └── README.md ├── static │ └── assets │ │ └── favicon.ico └── store │ └── README.md ├── aws └── iam_sample.json ├── bin └── deploy │ └── index.js ├── configs └── env.js ├── nuxt.config.js ├── package.json ├── scripts └── deploy │ ├── .eslintignore │ ├── .eslintrc.js │ ├── dist │ ├── constants.d.ts │ ├── constants.js │ ├── index.d.ts │ ├── index.js │ ├── lib │ │ ├── cloudFront.d.ts │ │ ├── cloudFront.js │ │ ├── commands.d.ts │ │ ├── commands.js │ │ ├── file.d.ts │ │ ├── file.js │ │ ├── s3.d.ts │ │ └── s3.js │ ├── processors │ │ ├── buildApp.d.ts │ │ ├── buildApp.js │ │ ├── buildFileContext.d.ts │ │ ├── buildFileContext.js │ │ ├── deleteOldObjects.d.ts │ │ ├── deleteOldObjects.js │ │ ├── deployApp.d.ts │ │ ├── deployApp.js │ │ ├── deployAssets.d.ts │ │ ├── deployAssets.js │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── purgeCDN.d.ts │ │ └── purgeCDN.js │ └── types │ │ ├── config.type.d.ts │ │ ├── config.type.js │ │ ├── contexts.type.d.ts │ │ ├── contexts.type.js │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── options.type.d.ts │ │ └── options.type.js │ ├── package.json │ ├── src │ ├── constants.ts │ ├── index.ts │ ├── lib │ │ ├── cloudFront.ts │ │ ├── commands.ts │ │ ├── file.ts │ │ └── s3.ts │ ├── processors │ │ ├── buildApp.ts │ │ ├── buildFileContext.ts │ │ ├── deleteOldObjects.ts │ │ ├── deployApp.ts │ │ ├── deployAssets.ts │ │ ├── index.ts │ │ └── purgeCDN.ts │ └── types │ │ ├── config.type.ts │ │ ├── contexts.type.ts │ │ └── index.ts │ ├── tsconfig.json │ └── yarn.lock ├── server ├── app.js ├── core │ └── nuxt.js ├── handler.js ├── local.js └── middlewares │ ├── cache-middleware.js │ ├── env-middleware.js │ ├── header-middleware.js │ └── logger-middleware.js ├── serverless.yml └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | executors: 4 | default: 5 | working_directory: ~/workspace 6 | docker: 7 | - image: circleci/node:12.16.2 8 | 9 | commands: 10 | save_app_modules: 11 | steps: 12 | - save_cache: 13 | paths: 14 | - ~/workspace/node_modules 15 | key: modules-{{ .Branch }}-{{ checksum "yarn.lock" }}-{{ checksum ".node-version" }} 16 | restore_app_modules: 17 | steps: 18 | - restore_cache: 19 | key: modules-{{ .Branch }}-{{ checksum "yarn.lock" }}-{{ checksum ".node-version" }} 20 | save_scripts_modules: 21 | steps: 22 | - save_cache: 23 | paths: 24 | - ~/workspace/scripts/deploy/node_modules 25 | key: modules-{{ .Branch }}-{{ checksum "scripts/deploy/yarn.lock" }}-{{ checksum ".node-version" }} 26 | restore_scripts_modules: 27 | steps: 28 | - restore_cache: 29 | key: modules-{{ .Branch }}-{{ checksum "scripts/deploy/yarn.lock" }}-{{ checksum ".node-version" }} 30 | 31 | jobs: 32 | install: 33 | executor: default 34 | steps: 35 | - checkout 36 | - restore_app_modules 37 | - restore_scripts_modules 38 | - run: 39 | name: Install app modules 40 | command: yarn install --frozen-lockfile 41 | - run: 42 | name: Install scripts modules 43 | working_directory: ~/workspace/scripts/deploy 44 | command: yarn install --frozen-lockfile 45 | - save_app_modules 46 | - save_scripts_modules 47 | lint: 48 | executor: default 49 | steps: 50 | - checkout 51 | - restore_app_modules 52 | - run: 53 | name: Lint 54 | command: yarn lint 55 | build-test: 56 | executor: default 57 | steps: 58 | - checkout 59 | - restore_app_modules 60 | - run: 61 | name: Build 62 | command: yarn build 63 | deploy: 64 | executor: default 65 | steps: 66 | - checkout 67 | - restore_app_modules 68 | - restore_scripts_modules 69 | - deploy: 70 | name: Deploy 71 | command: yarn deploy 72 | 73 | workflows: 74 | process: 75 | jobs: 76 | - install: 77 | filters: 78 | branches: 79 | only: /.*/ 80 | tags: 81 | only: /^v[0-9]+(\.[0-9]+){2}$/ 82 | - lint: 83 | requires: 84 | - install 85 | filters: 86 | branches: 87 | only: /.*/ 88 | tags: 89 | only: /^v[0-9]+(\.[0-9]+){2}$/ 90 | - build-test: 91 | requires: 92 | - lint 93 | filters: 94 | branches: 95 | only: /.*/ 96 | - deploy: 97 | requires: 98 | - lint 99 | filters: 100 | branches: 101 | ignore: /.*/ 102 | tags: 103 | only: /^v[0-9]+(\.[0-9]+){2}$/ 104 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | S3_BUCKET_NAME= 2 | S3_BUCKET_PREFIX= 3 | CLOUDFRONT_ID= 4 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | scripts 2 | node_modules 3 | dist 4 | .nuxt 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | node: true 6 | }, 7 | parserOptions: { 8 | parser: 'babel-eslint' 9 | }, 10 | extends: [ 11 | 'plugin:vue/recommended', 12 | 'plugin:prettier/recommended' 13 | ], 14 | // required to lint *.vue files 15 | plugins: [ 16 | 'vue', 17 | 'prettier' 18 | ], 19 | // add your custom rules here 20 | rules: { 21 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 22 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 23 | 'prettier/prettier': [ 24 | 'error', 25 | { 26 | singleQuote: true, 27 | trailingComma: 'all', 28 | }, 29 | ] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules 3 | 4 | # logs 5 | npm-debug.log 6 | yarn-error.log 7 | 8 | # Nuxt build 9 | .nuxt 10 | 11 | # Nuxt generate 12 | /dist 13 | 14 | .serverless 15 | 16 | .env 17 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 12.16.2 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 mya-ake 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nuxt.js on AWS Lambda 2 | 3 | ## Versions 4 | 5 | - Nuxt.js: 2.12.2 6 | - Node.js: 12.16.2 7 | - Lambda runtime: Node.js 12.x 8 | - 12.16.2(as of 2020-05-06) 9 | 10 | ## Commands 11 | 12 | ### Deploy 13 | 14 | #### Build & Deploy for API Gateway 15 | 16 | Endpoint: API Gateway 17 | Deploy to: Lambda 18 | 19 | ``` 20 | $ yarn deploy:api_gw 21 | ``` 22 | 23 | #### Build & Deploy for CloudFront 24 | 25 | Endpoint: CloudFront 26 | Deploy to: Lambda, S3 27 | 28 | ``` 29 | $ yarn deploy 30 | ``` 31 | 32 | ⚠️CloudFront and S3 are not created. Please create from the console. 33 | 34 | ### Remove Lambda 35 | 36 | ``` 37 | $ yarn delete 38 | ``` 39 | -------------------------------------------------------------------------------- /app/README.md: -------------------------------------------------------------------------------- 1 | # app 2 | 3 | > Nuxt.js project 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | $ npm install # Or yarn install 10 | 11 | # serve with hot reload at localhost:3000 12 | $ npm run dev 13 | 14 | # build for production and launch server 15 | $ npm run build 16 | $ npm start 17 | 18 | # generate static project 19 | $ npm run generate 20 | ``` 21 | 22 | For detailed explanation on how things work, checkout the [Nuxt.js docs](https://github.com/nuxt/nuxt.js). 23 | -------------------------------------------------------------------------------- /app/assets/README.md: -------------------------------------------------------------------------------- 1 | # ASSETS 2 | 3 | This directory contains your un-compiled assets such as LESS, SASS, or JavaScript. 4 | 5 | More information about the usage of this directory in the documentation: 6 | https://nuxtjs.org/guide/assets#webpacked 7 | 8 | **This directory is not required, you can delete it if you don't want to use it.** 9 | -------------------------------------------------------------------------------- /app/components/Logo.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 80 | -------------------------------------------------------------------------------- /app/components/README.md: -------------------------------------------------------------------------------- 1 | # COMPONENTS 2 | 3 | The components directory contains your Vue.js Components. 4 | Nuxt.js doesn't supercharge these components. 5 | 6 | **This directory is not required, you can delete it if you don't want to use it.** 7 | -------------------------------------------------------------------------------- /app/layouts/README.md: -------------------------------------------------------------------------------- 1 | # LAYOUTS 2 | 3 | This directory contains your Application Layouts. 4 | 5 | More information about the usage of this directory in the documentation: 6 | https://nuxtjs.org/guide/views#layouts 7 | 8 | **This directory is not required, you can delete it if you don't want to use it.** 9 | -------------------------------------------------------------------------------- /app/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 54 | -------------------------------------------------------------------------------- /app/layouts/error.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/middleware/README.md: -------------------------------------------------------------------------------- 1 | # MIDDLEWARE 2 | 3 | This directory contains your Application Middleware. 4 | The middleware lets you define custom function to be ran before rendering a page or a group of pages (layouts). 5 | 6 | More information about the usage of this directory in the documentation: 7 | https://nuxtjs.org/guide/routing#middleware 8 | 9 | **This directory is not required, you can delete it if you don't want to use it.** 10 | -------------------------------------------------------------------------------- /app/pages/README.md: -------------------------------------------------------------------------------- 1 | # PAGES 2 | 3 | This directory contains your Application Views and Routes. 4 | The framework reads all the .vue files inside this directory and create the router of your application. 5 | 6 | More information about the usage of this directory in the documentation: 7 | https://nuxtjs.org/guide/routing 8 | -------------------------------------------------------------------------------- /app/pages/about.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 28 | -------------------------------------------------------------------------------- /app/pages/index.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 49 | 50 | 81 | -------------------------------------------------------------------------------- /app/plugins/README.md: -------------------------------------------------------------------------------- 1 | # PLUGINS 2 | 3 | This directory contains your Javascript plugins that you want to run before instantiating the root vue.js application. 4 | 5 | More information about the usage of this directory in the documentation: 6 | https://nuxtjs.org/guide/plugins 7 | 8 | **This directory is not required, you can delete it if you don't want to use it.** 9 | -------------------------------------------------------------------------------- /app/static/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mya-ake/nuxt-on-lambda/5774e5dccd741092e03ce19c825d3c216c3b0abe/app/static/assets/favicon.ico -------------------------------------------------------------------------------- /app/store/README.md: -------------------------------------------------------------------------------- 1 | # STORE 2 | 3 | This directory contains your Vuex Store files. 4 | Vuex Store option is implemented in the Nuxt.js framework. 5 | Creating a index.js file in this directory activate the option in the framework automatically. 6 | 7 | More information about the usage of this directory in the documentation: 8 | https://nuxtjs.org/guide/vuex-store 9 | 10 | **This directory is not required, you can delete it if you don't want to use it.** 11 | -------------------------------------------------------------------------------- /aws/iam_sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "VisualEditor0", 6 | "Effect": "Allow", 7 | "Action": [ 8 | "lambda:CreateFunction", 9 | "lambda:ListVersionsByFunction", 10 | "lambda:GetFunctionConfiguration", 11 | "lambda:DeleteFunction", 12 | "lambda:GetFunction", 13 | "lambda:UpdateFunctionConfiguration", 14 | "lambda:UpdateFunctionCode", 15 | "lambda:AddPermission", 16 | "lambda:PublishVersion", 17 | "cloudformation:CancelUpdateStack", 18 | "cloudformation:DescribeStackResource", 19 | "cloudformation:DescribeStackEvents", 20 | "cloudformation:UpdateStack", 21 | "cloudformation:ListStackResources", 22 | "cloudformation:DescribeStackInstance", 23 | "cloudformation:DescribeStackSet", 24 | "cloudformation:CreateStack", 25 | "cloudformation:DeleteStack", 26 | "cloudformation:DescribeStackResources", 27 | "cloudformation:DescribeStacks", 28 | "cloudformation:ValidateTemplate", 29 | "iam:CreateRole", 30 | "iam:PutRolePolicy", 31 | "iam:PassRole", 32 | "iam:GetRole", 33 | "iam:UpdateRole", 34 | "iam:DeleteRole", 35 | "iam:DeleteRolePolicy", 36 | "s3:CreateBucket", 37 | "s3:ListBucket", 38 | "s3:PutEncryptionConfiguration", 39 | "s3:DeleteObject", 40 | "s3:DeleteBucket", 41 | "s3:PutObject", 42 | "s3:GetObject", 43 | "cloudfront:CreateInvalidation", 44 | "apigateway:*", 45 | "logs:DescribeLogGroups", 46 | "logs:DeleteLogGroup", 47 | "logs:CreateLogGroup" 48 | ], 49 | "Resource": "*" 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /bin/deploy/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | require('dotenv').config(); 3 | 4 | const { deploy } = require('./../../scripts/deploy'); 5 | const nuxtConfig = require('./../../nuxt.config'); 6 | 7 | const ROOT_DIR = process.cwd(); 8 | const SRC_DIR = path.join(ROOT_DIR, nuxtConfig.srcDir); 9 | const NUXT_DIR = path.join(ROOT_DIR, '.nuxt'); 10 | const NUXT_CLIENT_DIR = path.join(NUXT_DIR, 'dist', 'client'); 11 | const NUXT_STATIC_DIR = path.join(SRC_DIR, 'static'); 12 | const NUXT_GENERATED_ERROR_PAGES_DIR = path.join(ROOT_DIR, 'dist'); 13 | 14 | const assetsDirs = [ 15 | { pathname: NUXT_CLIENT_DIR, options: { prefix: '_nuxt' } }, 16 | { pathname: NUXT_STATIC_DIR }, 17 | { 18 | pathname: NUXT_GENERATED_ERROR_PAGES_DIR, 19 | options: { 20 | prefix: '_static_pages', 21 | includes: ['404.html', '**/403/index.html', '**/500/index.html'], 22 | }, 23 | }, 24 | ]; 25 | const s3Bucket = { 26 | name: process.env.S3_BUCKET_NAME, 27 | prefix: process.env.S3_BUCKET_PREFIX, 28 | }; 29 | const cloudFrontId = process.env.CLOUDFRONT_ID; 30 | const buildCommands = ['yarn build', 'yarn generate:error']; 31 | const cacheControl = `public, max-age=${60 * 60 * 24 * 7}`; // e.g. one week 32 | 33 | deploy({ assetsDirs, s3Bucket, cloudFrontId, buildCommands, cacheControl }); 34 | -------------------------------------------------------------------------------- /configs/env.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const endpointEnv = process.env.ENDPOINT_ENV || 'cf'; 4 | 5 | const ENV = { 6 | STAGE: 'dev', 7 | BASE_URL: '', 8 | ENDPOINT_ENV: endpointEnv, 9 | NODE_ENV: process.env.NODE_ENV || '', 10 | GENERATE_ERROR_PAGE: Boolean(process.env.GENERATE_ERROR_PAGE), 11 | }; 12 | 13 | if (endpointEnv === 'api_gw') { 14 | ENV.BASE_URL = `/${ENV.STAGE}/`; 15 | } 16 | 17 | // for serverless.yml 18 | const exporter = () => { 19 | return ENV; 20 | }; 21 | 22 | module.exports = { 23 | ENV, 24 | exporter, 25 | }; 26 | -------------------------------------------------------------------------------- /nuxt.config.js: -------------------------------------------------------------------------------- 1 | const { ENV } = require('./configs/env'); 2 | 3 | const routerConfig = {}; 4 | if (ENV.BASE_URL) { 5 | routerConfig.base = ENV.BASE_URL; 6 | } 7 | 8 | const generate = {}; 9 | if (ENV.GENERATE_ERROR_PAGE) { 10 | generate.routes = ['/403', '/404', '/500']; 11 | } 12 | 13 | module.exports = { 14 | mode: 'universal', 15 | 16 | srcDir: 'app', 17 | 18 | router: { 19 | ...routerConfig, 20 | }, 21 | 22 | render: { 23 | /** 24 | * compression を通すと2重に Gzip がかかりブラウザが表示できないので 25 | * なにもしないミドルウェアを定義しておく 26 | */ 27 | compressor: (req, res, next) => { 28 | next(); 29 | }, 30 | }, 31 | 32 | /* 33 | ** Headers of the page 34 | */ 35 | head: { 36 | title: 'Nuxt.js on AWS Lambda', 37 | meta: [ 38 | { charset: 'utf-8' }, 39 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 40 | { hid: 'description', name: 'description', content: 'Nuxt.js project' }, 41 | ], 42 | link: [{ rel: 'icon', type: 'image/x-icon', href: '/assets/favicon.ico' }], 43 | }, 44 | /* 45 | ** Customize the progress bar color 46 | */ 47 | loading: { color: '#fff' }, 48 | /* 49 | ** Global CSS 50 | */ 51 | css: [], 52 | 53 | /* 54 | ** Plugins to load before mounting the App 55 | */ 56 | plugins: [], 57 | 58 | /* 59 | ** Nuxt.js modules 60 | */ 61 | modules: [], 62 | 63 | /* 64 | ** Build configuration 65 | */ 66 | build: { 67 | /* 68 | ** You can extend webpack config here 69 | */ 70 | extend(config, ctx) { 71 | // Run ESLint on save 72 | if (ctx.isDev && ctx.isClient) { 73 | config.module.rules.push({ 74 | enforce: 'pre', 75 | test: /\.(js|vue)$/, 76 | loader: 'eslint-loader', 77 | exclude: /(node_modules)/, 78 | }); 79 | } 80 | }, 81 | }, 82 | 83 | generate, 84 | 85 | env: { 86 | GENERATE_ERROR_PAGE: ENV.GENERATE_ERROR_PAGE, 87 | NODE_VERSION: process.versions.node, 88 | }, 89 | }; 90 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-on-lambda", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "repository": "https://github.com/mya-ake/nuxt-on-lambda.git", 6 | "author": "t.shibuta ", 7 | "license": "MIT", 8 | "scripts": { 9 | "dev": "cross-env NODE_ENV=development nodemon server/local.js --watch server", 10 | "build": "nuxt build", 11 | "start": "cross-env NODE_ENV=production node server/local.js", 12 | "generate:error": "cross-env NODE_ENV=production GENERATE_ERROR_PAGE=true nuxt generate", 13 | "lint": "vue-cli-service lint --no-fix .", 14 | "lint:fix": "vue-cli-service lint .", 15 | "precommit": "npm run lint", 16 | "sls": "sls", 17 | "sls:deploy": "sls deploy", 18 | "deploy": "cross-env NODE_ENV=production ENDPOINT_ENV=cf node bin/deploy/index.js", 19 | "deploy:api_gw": "cross-env NODE_ENV=production ENDPOINT_ENV=api_gw run-s build sls:deploy", 20 | "delete": "sls remove" 21 | }, 22 | "dependencies": { 23 | "@nuxtjs/dotenv": "^1.4.1", 24 | "aws-serverless-express": "^3.3.8", 25 | "cross-env": "^7.0.2", 26 | "express": "^4.16.4", 27 | "nuxt": "^2.12.2" 28 | }, 29 | "devDependencies": { 30 | "@vue/cli-plugin-eslint": "^4.3.1", 31 | "@vue/cli-service": "^4.3.1", 32 | "@vue/eslint-config-prettier": "^6.0.0", 33 | "babel-eslint": "^10.1.0", 34 | "eslint": "^6.8.0", 35 | "eslint-plugin-prettier": "^3.1.3", 36 | "eslint-plugin-vue": "^6.2.2", 37 | "nodemon": "^2.0.3", 38 | "npm-run-all": "^4.1.3", 39 | "serverless": "^1.69.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /scripts/deploy/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | -------------------------------------------------------------------------------- /scripts/deploy/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | "extends": [ 4 | "plugin:prettier/recommended" 5 | ], 6 | "plugins": [ 7 | "@typescript-eslint" 8 | ], 9 | "parser": "@typescript-eslint/parser", 10 | "parserOptions": { 11 | "sourceType": "module", 12 | "project": "./tsconfig.json" 13 | }, 14 | "rules": { 15 | "@typescript-eslint/adjacent-overload-signatures": "error", 16 | 'prettier/prettier': [ 17 | 'error', 18 | { 19 | singleQuote: true, 20 | trailingComma: 'all', 21 | }, 22 | ], 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /scripts/deploy/dist/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare const CONTENT_TYPES: { 2 | [key: string]: string; 3 | }; 4 | -------------------------------------------------------------------------------- /scripts/deploy/dist/constants.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.CONTENT_TYPES = Object.freeze({ 4 | html: 'text/html; charset=utf-8', 5 | js: 'application/javascript; charset=utf-8', 6 | css: 'text/css; charset=utf-8', 7 | map: 'application/octet-stream; charset=utf-8', 8 | json: 'application/json; charset=utf-8', 9 | jpg: 'image/jpeg', 10 | png: 'image/png', 11 | svg: 'image/svg+xml', 12 | ico: 'image/x-icon', 13 | xml: 'application/xml; charset=utf-8', 14 | woff: 'application/font-woff', 15 | ttf: 'application/x-font-ttf', 16 | eot: 'application/vnd.ms-fontobject', 17 | plane: 'text/plain; charset=utf-8', 18 | webmanifest: 'application/json; charset=utf-8', 19 | }); 20 | -------------------------------------------------------------------------------- /scripts/deploy/dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import { DeployConfig } from 'src/types'; 2 | export declare const deploy: (config: DeployConfig) => Promise; 3 | -------------------------------------------------------------------------------- /scripts/deploy/dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const consola_1 = __importDefault(require("consola")); 7 | const processors_1 = require("./processors"); 8 | exports.deploy = async (config) => { 9 | const { assetsDirs, s3Bucket, cloudFrontId, buildCommands } = config; 10 | try { 11 | await processors_1.buildApp(buildCommands); 12 | const fileContexts = await processors_1.buildFileContextsTogether(assetsDirs); 13 | await processors_1.deployAssets({ fileContexts, s3Bucket, deployConifg: config }); 14 | await processors_1.deployApp(); 15 | await processors_1.deleteOldObjects({ 16 | s3Bucket, 17 | }); 18 | await processors_1.purgeCDN({ cloudFrontId }); 19 | consola_1.default.success('Deploy completed'); 20 | } 21 | catch (err) { 22 | consola_1.default.error(err); 23 | process.exit(1); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /scripts/deploy/dist/lib/cloudFront.d.ts: -------------------------------------------------------------------------------- 1 | import { CloudFront } from 'aws-sdk'; 2 | export declare const createInvalidation: (params: CloudFront.CreateInvalidationRequest) => Promise; 3 | -------------------------------------------------------------------------------- /scripts/deploy/dist/lib/cloudFront.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const aws_sdk_1 = require("aws-sdk"); 4 | const cloudFront = new aws_sdk_1.CloudFront(); 5 | exports.createInvalidation = (params) => { 6 | return new Promise((resolve, reject) => { 7 | cloudFront.createInvalidation(params, (err, data) => { 8 | if (err) { 9 | reject(err); 10 | } 11 | else { 12 | resolve(data); 13 | } 14 | }); 15 | }); 16 | }; 17 | -------------------------------------------------------------------------------- /scripts/deploy/dist/lib/commands.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { ChildProcess } from 'child_process'; 3 | declare type spawn = (command: string, args?: string[]) => Promise; 4 | export declare const spawn: spawn; 5 | export {}; 6 | -------------------------------------------------------------------------------- /scripts/deploy/dist/lib/commands.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const cross_spawn_1 = __importDefault(require("cross-spawn")); 7 | exports.spawn = (command, args = []) => { 8 | return new Promise((resolve, reject) => { 9 | const ps = cross_spawn_1.default(command, args, { stdio: 'inherit' }); 10 | ps.on('close', () => { 11 | resolve(ps); 12 | }); 13 | ps.on('error', err => { 14 | reject(err); 15 | }); 16 | ps.on('exit', code => { 17 | if (code === 0) { 18 | return; 19 | } 20 | reject(code); 21 | }); 22 | }); 23 | }; 24 | -------------------------------------------------------------------------------- /scripts/deploy/dist/lib/file.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const extractFileName: (pathname: string) => string; 3 | export declare const extractExtension: (pathname: string) => string; 4 | export declare const isDirectory: (pathname: string) => Promise; 5 | export declare const getFilePathnames: (dirPathname: string) => Promise; 6 | export declare const readFile: (pathname: string) => Promise; 7 | -------------------------------------------------------------------------------- /scripts/deploy/dist/lib/file.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const fs_1 = __importDefault(require("fs")); 7 | const path_1 = __importDefault(require("path")); 8 | const util_1 = require("util"); 9 | const fsPromises = { 10 | stat: util_1.promisify(fs_1.default.stat), 11 | readdir: util_1.promisify(fs_1.default.readdir), 12 | readFile: util_1.promisify(fs_1.default.readFile), 13 | mkdir: util_1.promisify(fs_1.default.mkdir), 14 | writeFile: util_1.promisify(fs_1.default.writeFile), 15 | }; 16 | exports.extractFileName = (pathname) => { 17 | return pathname.split('/').pop() || ''; 18 | }; 19 | exports.extractExtension = (pathname) => { 20 | return pathname.split('.').pop() || ''; 21 | }; 22 | exports.isDirectory = async (pathname) => { 23 | const pathState = await fsPromises.stat(pathname); 24 | return pathState.isDirectory(); 25 | }; 26 | exports.getFilePathnames = async (dirPathname) => { 27 | const pathnames = await fsPromises.readdir(dirPathname); 28 | let allPathnames = []; 29 | for (const pathname of pathnames) { 30 | const absoluteFilePathname = path_1.default.join(dirPathname, pathname); 31 | if (await exports.isDirectory(absoluteFilePathname)) { 32 | const nestedFilePathnames = await exports.getFilePathnames(absoluteFilePathname); 33 | allPathnames = allPathnames.concat(nestedFilePathnames); 34 | } 35 | else { 36 | allPathnames = allPathnames.concat(absoluteFilePathname); 37 | } 38 | } 39 | return allPathnames; 40 | }; 41 | exports.readFile = (pathname) => { 42 | return fsPromises.readFile(pathname); 43 | }; 44 | const existPathname = async (pathname) => { 45 | try { 46 | await fsPromises.stat(pathname); 47 | return true; 48 | } 49 | catch (err) { 50 | return false; 51 | } 52 | }; 53 | const createDir = (pathname) => { 54 | return fsPromises.mkdir(pathname); 55 | }; 56 | const ensureWriteProcess = async (pathname) => { 57 | const fileDirname = path_1.default.dirname(pathname); 58 | if (await existPathname(fileDirname)) { 59 | return; 60 | } 61 | await ensureWriteProcess(fileDirname); 62 | await createDir(fileDirname); 63 | }; 64 | -------------------------------------------------------------------------------- /scripts/deploy/dist/lib/s3.d.ts: -------------------------------------------------------------------------------- 1 | import S3 = require('aws-sdk/clients/s3'); 2 | export declare const listObjects: (params: S3.ListObjectsV2Request) => Promise; 3 | export declare const putObject: (params: S3.PutObjectRequest) => Promise; 4 | export declare const deleteObjects: (params: S3.DeleteObjectsRequest) => Promise; 5 | -------------------------------------------------------------------------------- /scripts/deploy/dist/lib/s3.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const S3 = require("aws-sdk/clients/s3"); 4 | const s3 = new S3(); 5 | exports.listObjects = (params) => { 6 | return new Promise((resolve, reject) => { 7 | s3.listObjectsV2(params, (err, data) => { 8 | if (err) { 9 | reject(err); 10 | return; 11 | } 12 | if (typeof data.Contents === 'undefined') { 13 | resolve([]); 14 | return; 15 | } 16 | resolve(data.Contents); 17 | }); 18 | }); 19 | }; 20 | exports.putObject = (params) => { 21 | return new Promise((resolve, reject) => { 22 | s3.putObject(params, (err, data) => { 23 | if (err) { 24 | reject(err); 25 | } 26 | else { 27 | resolve(data); 28 | } 29 | }); 30 | }); 31 | }; 32 | exports.deleteObjects = (params) => { 33 | return new Promise((resolve, reject) => { 34 | s3.deleteObjects(params, (err, data) => { 35 | if (err) { 36 | reject(err); 37 | } 38 | else { 39 | resolve(data); 40 | } 41 | }); 42 | }); 43 | }; 44 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/buildApp.d.ts: -------------------------------------------------------------------------------- 1 | export declare const buildApp: (buildCommands: string[]) => Promise; 2 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/buildApp.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const consola_1 = __importDefault(require("consola")); 7 | const commands_1 = require("./../lib/commands"); 8 | exports.buildApp = async (buildCommands) => { 9 | for (let i = 0; i < buildCommands.length; ++i) { 10 | const command = buildCommands[i]; 11 | const parsedCommand = command.split(/\s/); 12 | const commandName = parsedCommand.shift(); 13 | if (typeof commandName !== 'string' || commandName.length === 0) { 14 | consola_1.default.info(`Skip build command: \`${command}\`, index: ${i}`); 15 | continue; 16 | } 17 | await commands_1.spawn(commandName, parsedCommand); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/buildFileContext.d.ts: -------------------------------------------------------------------------------- 1 | import { FileContext, AssetsDirContext } from 'src/types'; 2 | export declare const buildFileContextsTogether: (assetsDirContexts: AssetsDirContext[]) => Promise; 3 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/buildFileContext.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const path_1 = __importDefault(require("path")); 7 | const minimatch_1 = __importDefault(require("minimatch")); 8 | const file_1 = require("../lib/file"); 9 | const constants_1 = require("../constants"); 10 | const selectContentType = (extension) => { 11 | return extension in constants_1.CONTENT_TYPES 12 | ? constants_1.CONTENT_TYPES[extension] 13 | : constants_1.CONTENT_TYPES['plane']; 14 | }; 15 | const buildFileContext = ({ absolutePathname, assetsDirContext, }) => { 16 | const { pathname: dirPathname } = assetsDirContext; 17 | const { options = { prefix: '' } } = assetsDirContext; 18 | const fileName = file_1.extractFileName(absolutePathname); 19 | const extension = file_1.extractExtension(fileName); 20 | const { prefix = '' } = options; 21 | const relativePathname = absolutePathname.replace(dirPathname, ''); 22 | const s3Key = path_1.default.join(prefix, relativePathname).replace(/^\//, ''); 23 | const contentType = selectContentType(extension); 24 | return { 25 | fileName, 26 | absolutePathname, 27 | s3Key, 28 | contentType, 29 | }; 30 | }; 31 | const isMatch = ({ pathname, assetsDirContext, }) => { 32 | if (assetsDirContext.options == null) { 33 | return true; 34 | } 35 | const { includes = [] } = assetsDirContext.options; 36 | if (includes.length === 0) { 37 | return true; 38 | } 39 | return includes.some(match => { 40 | return minimatch_1.default(pathname, match, { matchBase: true, dot: true }); 41 | }); 42 | }; 43 | const buildFileContexts = async (assetsDirContext) => { 44 | const isFile = !(await file_1.isDirectory(assetsDirContext.pathname)); 45 | const pathnames = isFile 46 | ? [assetsDirContext.pathname] 47 | : await file_1.getFilePathnames(assetsDirContext.pathname); 48 | const contexts = pathnames 49 | .filter(pathname => { 50 | return isMatch({ pathname, assetsDirContext }); 51 | }) 52 | .map(pathname => { 53 | return buildFileContext({ 54 | absolutePathname: pathname, 55 | assetsDirContext, 56 | }); 57 | }); 58 | return contexts; 59 | }; 60 | exports.buildFileContextsTogether = async (assetsDirContexts) => { 61 | let contexts = []; 62 | for (const assetsDirContext of assetsDirContexts) { 63 | contexts = contexts.concat(await buildFileContexts(assetsDirContext)); 64 | } 65 | return contexts; 66 | }; 67 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/deleteOldObjects.d.ts: -------------------------------------------------------------------------------- 1 | import { S3Bucket } from 'src/types'; 2 | declare type deleteOldObjects = (params: { 3 | s3Bucket: S3Bucket; 4 | }) => Promise; 5 | export declare const deleteOldObjects: deleteOldObjects; 6 | export {}; 7 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/deleteOldObjects.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const consola_1 = __importDefault(require("consola")); 7 | const dayjs_1 = __importDefault(require("dayjs")); 8 | const s3_1 = require("../lib/s3"); 9 | const buildLastModified = (lastModified) => { 10 | if (typeof lastModified === 'undefined') { 11 | return new Date(0); 12 | } 13 | return lastModified; 14 | }; 15 | const listS3Objects = async ({ s3Bucket }) => { 16 | const objects = await s3_1.listObjects({ Bucket: s3Bucket.name }); 17 | return objects.map(({ Key, LastModified }) => ({ 18 | key: Key || '', 19 | lastModified: buildLastModified(LastModified), 20 | })); 21 | }; 22 | const isObjectToDelete = (s3ObjectContext) => { 23 | const { lastModified } = s3ObjectContext; 24 | const currentDate = dayjs_1.default(new Date()); 25 | const modifiedDate = dayjs_1.default(lastModified); 26 | return currentDate.diff(modifiedDate, 'day') > 7; 27 | }; 28 | const deleteS3Objects = async ({ s3Bucket, objectsToDelete, }) => { 29 | const objects = objectsToDelete.map(({ key }) => ({ Key: key })); 30 | await s3_1.deleteObjects({ 31 | Bucket: s3Bucket.name, 32 | Delete: { 33 | Objects: objects, 34 | }, 35 | }); 36 | objectsToDelete.forEach(({ key }) => consola_1.default.success(`Deleted: ${key}`)); 37 | }; 38 | exports.deleteOldObjects = async ({ s3Bucket }) => { 39 | const objects = await listS3Objects({ s3Bucket }); 40 | const objectsToDelete = objects.filter(isObjectToDelete); 41 | if (objectsToDelete.length === 0) { 42 | consola_1.default.info('There is no old object.'); 43 | return; 44 | } 45 | await deleteS3Objects({ s3Bucket, objectsToDelete }); 46 | }; 47 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/deployApp.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export declare const deployApp: () => Promise; 3 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/deployApp.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const commands_1 = require("./../lib/commands"); 4 | exports.deployApp = () => { 5 | return commands_1.spawn('yarn', ['sls:deploy']); 6 | }; 7 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/deployAssets.d.ts: -------------------------------------------------------------------------------- 1 | import { FileContext, S3Bucket, DeployConfig } from 'src/types'; 2 | declare type deployAssets = (params: { 3 | fileContexts: FileContext[]; 4 | s3Bucket: S3Bucket; 5 | deployConifg: DeployConfig; 6 | }) => Promise; 7 | export declare const deployAssets: deployAssets; 8 | export {}; 9 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/deployAssets.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const consola_1 = __importDefault(require("consola")); 7 | const path_1 = __importDefault(require("path")); 8 | const s3_1 = require("../lib/s3"); 9 | const file_1 = require("../lib/file"); 10 | const buildKey = ({ prefix = '', relativePathname, }) => { 11 | const key = path_1.default.join(prefix, relativePathname); 12 | return key.replace(/^\//, ''); 13 | }; 14 | const createCacheControlBuilder = (deployConfig) => { 15 | const { cacheControl } = deployConfig; 16 | if (typeof cacheControl === 'function') { 17 | return cacheControl; 18 | } 19 | return () => cacheControl; 20 | }; 21 | const buildParams = async ({ fileContext, s3Bucket, cacheControlBuilder, }) => { 22 | const body = await file_1.readFile(fileContext.absolutePathname); 23 | return { 24 | Bucket: s3Bucket.name, 25 | Key: buildKey({ 26 | prefix: s3Bucket.prefix, 27 | relativePathname: fileContext.s3Key, 28 | }), 29 | Body: body, 30 | ContentType: fileContext.contentType, 31 | CacheControl: cacheControlBuilder(fileContext), 32 | }; 33 | }; 34 | exports.deployAssets = async ({ fileContexts, s3Bucket, deployConifg, }) => { 35 | const cacheControlBuilder = createCacheControlBuilder(deployConifg); 36 | for (const fileContext of fileContexts) { 37 | const params = await buildParams({ 38 | fileContext, 39 | s3Bucket, 40 | cacheControlBuilder, 41 | }); 42 | await s3_1.putObject(params); 43 | consola_1.default.success(`Deployed: ${fileContext.s3Key}`); 44 | } 45 | return; 46 | }; 47 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './buildFileContext'; 2 | export * from './deployAssets'; 3 | export * from './deleteOldObjects'; 4 | export * from './buildApp'; 5 | export * from './deployApp'; 6 | export * from './purgeCDN'; 7 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function __export(m) { 3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; 4 | } 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | __export(require("./buildFileContext")); 7 | __export(require("./deployAssets")); 8 | __export(require("./deleteOldObjects")); 9 | __export(require("./buildApp")); 10 | __export(require("./deployApp")); 11 | __export(require("./purgeCDN")); 12 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/purgeCDN.d.ts: -------------------------------------------------------------------------------- 1 | export declare const purgeCDN: ({ cloudFrontId, items, }: { 2 | cloudFrontId: string; 3 | items?: string[] | undefined; 4 | }) => Promise; 5 | -------------------------------------------------------------------------------- /scripts/deploy/dist/processors/purgeCDN.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const consola_1 = __importDefault(require("consola")); 7 | const cloudFront_1 = require("./../lib/cloudFront"); 8 | exports.purgeCDN = async ({ cloudFrontId, items = ['/*'], }) => { 9 | consola_1.default.info('Start purging CDN'); 10 | await cloudFront_1.createInvalidation({ 11 | DistributionId: cloudFrontId, 12 | InvalidationBatch: { 13 | CallerReference: String(new Date().getTime()), 14 | Paths: { 15 | Quantity: 1, 16 | Items: items, 17 | }, 18 | }, 19 | }); 20 | consola_1.default.success('Succeeded in purging CDN'); 21 | }; 22 | -------------------------------------------------------------------------------- /scripts/deploy/dist/types/config.type.d.ts: -------------------------------------------------------------------------------- 1 | import { AssetsDirContext, FileContext } from './contexts.type'; 2 | export interface S3Bucket { 3 | name: string; 4 | prefix?: string; 5 | } 6 | export interface DeployConfig { 7 | assetsDirs: AssetsDirContext[]; 8 | s3Bucket: S3Bucket; 9 | cloudFrontId: string; 10 | buildCommands: string[]; 11 | cacheControl: string | ((fileContext: FileContext) => string); 12 | } 13 | -------------------------------------------------------------------------------- /scripts/deploy/dist/types/config.type.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /scripts/deploy/dist/types/contexts.type.d.ts: -------------------------------------------------------------------------------- 1 | export interface FileContext { 2 | fileName: string; 3 | absolutePathname: string; 4 | s3Key: string; 5 | contentType: string; 6 | } 7 | export interface AssetsDirContext { 8 | pathname: string; 9 | options?: { 10 | prefix?: string; 11 | includes?: string[]; 12 | }; 13 | } 14 | export interface S3ObjectContext { 15 | key: string; 16 | lastModified: Date; 17 | } 18 | -------------------------------------------------------------------------------- /scripts/deploy/dist/types/contexts.type.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /scripts/deploy/dist/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './config.type'; 2 | export * from './contexts.type'; 3 | -------------------------------------------------------------------------------- /scripts/deploy/dist/types/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /scripts/deploy/dist/types/options.type.d.ts: -------------------------------------------------------------------------------- 1 | import { AssetsDirContext } from './contexts.type'; 2 | export interface S3Bucket { 3 | name: string; 4 | prefix?: string; 5 | } 6 | export interface DeployOptions { 7 | assetsDirs: AssetsDirContext[]; 8 | s3Bucket: S3Bucket; 9 | cloudFrontId: string; 10 | } 11 | -------------------------------------------------------------------------------- /scripts/deploy/dist/types/options.type.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /scripts/deploy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-on-lambda-deploy", 3 | "version": "1.0.0", 4 | "main": "dist/index.js", 5 | "types": "dist/index.d.ts", 6 | "license": "MIT", 7 | "scripts": { 8 | "tsc": "tsc", 9 | "lint": "eslint ./src/**/*.ts ./src/*.ts", 10 | "lint:fix": "eslint --fix ./src/**/*.ts ./src/*.ts" 11 | }, 12 | "devDependencies": { 13 | "@types/cross-spawn": "^6.0.0", 14 | "@types/node": "^12.0.10", 15 | "@typescript-eslint/eslint-plugin": "^1.10.2", 16 | "@typescript-eslint/parser": "^1.10.2", 17 | "cross-spawn": "^6.0.5", 18 | "eslint": "^6.0.0", 19 | "eslint-config-prettier": "^5.0.0", 20 | "eslint-plugin-prettier": "^3.1.0", 21 | "prettier": "^1.18.2", 22 | "typescript": "^3.5.2" 23 | }, 24 | "dependencies": { 25 | "aws-sdk": "^2.480.0", 26 | "consola": "^2.9.0", 27 | "dayjs": "^1.8.14", 28 | "minimatch": "^3.0.4" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /scripts/deploy/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const CONTENT_TYPES: { [key: string]: string } = Object.freeze({ 2 | html: 'text/html; charset=utf-8', 3 | js: 'application/javascript; charset=utf-8', 4 | css: 'text/css; charset=utf-8', 5 | map: 'application/octet-stream; charset=utf-8', 6 | json: 'application/json; charset=utf-8', 7 | jpg: 'image/jpeg', 8 | png: 'image/png', 9 | svg: 'image/svg+xml', 10 | ico: 'image/x-icon', 11 | xml: 'application/xml; charset=utf-8', 12 | woff: 'application/font-woff', 13 | ttf: 'application/x-font-ttf', 14 | eot: 'application/vnd.ms-fontobject', 15 | plane: 'text/plain; charset=utf-8', 16 | webmanifest: 'application/json; charset=utf-8', 17 | }); 18 | -------------------------------------------------------------------------------- /scripts/deploy/src/index.ts: -------------------------------------------------------------------------------- 1 | import consola from 'consola'; 2 | import { 3 | buildFileContextsTogether, 4 | deployAssets, 5 | deleteOldObjects, 6 | buildApp, 7 | deployApp, 8 | purgeCDN, 9 | } from './processors'; 10 | import { DeployConfig } from 'src/types'; 11 | 12 | export const deploy = async (config: DeployConfig) => { 13 | const { assetsDirs, s3Bucket, cloudFrontId, buildCommands } = config; 14 | 15 | try { 16 | await buildApp(buildCommands); 17 | 18 | const fileContexts = await buildFileContextsTogether(assetsDirs); 19 | 20 | await deployAssets({ fileContexts, s3Bucket, deployConifg: config }); 21 | await deployApp(); 22 | 23 | await deleteOldObjects({ 24 | s3Bucket, 25 | }); 26 | await purgeCDN({ cloudFrontId }); 27 | consola.success('Deploy completed'); 28 | } catch (err) { 29 | consola.error(err); 30 | process.exit(1); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /scripts/deploy/src/lib/cloudFront.ts: -------------------------------------------------------------------------------- 1 | import { CloudFront } from 'aws-sdk'; 2 | 3 | const cloudFront = new CloudFront(); 4 | 5 | export const createInvalidation = ( 6 | params: CloudFront.CreateInvalidationRequest, 7 | ) => { 8 | return new Promise((resolve, reject) => { 9 | cloudFront.createInvalidation(params, (err, data) => { 10 | if (err) { 11 | reject(err); 12 | } else { 13 | resolve(data); 14 | } 15 | }); 16 | }); 17 | }; 18 | -------------------------------------------------------------------------------- /scripts/deploy/src/lib/commands.ts: -------------------------------------------------------------------------------- 1 | import spawnCommand from 'cross-spawn' 2 | import { ChildProcess } from 'child_process'; 3 | 4 | type spawn = (command: string, args?: string[]) => Promise; 5 | 6 | export const spawn: spawn = (command, args = []) => { 7 | return new Promise((resolve, reject) => { 8 | const ps = spawnCommand(command, args, { stdio: 'inherit' }); 9 | ps.on('close', () => { 10 | resolve(ps); 11 | }); 12 | ps.on('error', err => { 13 | reject(err); 14 | }); 15 | ps.on('exit', code => { 16 | if (code === 0) { 17 | return; 18 | } 19 | reject(code); 20 | }); 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /scripts/deploy/src/lib/file.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { promisify } from 'util'; 4 | 5 | const fsPromises = { 6 | stat: promisify(fs.stat), 7 | readdir: promisify(fs.readdir), 8 | readFile: promisify(fs.readFile), 9 | mkdir: promisify(fs.mkdir), 10 | writeFile: promisify(fs.writeFile), 11 | }; 12 | 13 | export const extractFileName = (pathname: string): string => { 14 | return pathname.split('/').pop() || ''; 15 | }; 16 | 17 | export const extractExtension = (pathname: string): string => { 18 | return pathname.split('.').pop() || ''; 19 | }; 20 | 21 | export const isDirectory = async (pathname: string) => { 22 | const pathState = await fsPromises.stat(pathname); 23 | return pathState.isDirectory(); 24 | }; 25 | 26 | export const getFilePathnames = async (dirPathname: string) => { 27 | const pathnames = await fsPromises.readdir(dirPathname); 28 | let allPathnames: string[] = []; 29 | for (const pathname of pathnames) { 30 | const absoluteFilePathname = path.join(dirPathname, pathname); 31 | if (await isDirectory(absoluteFilePathname)) { 32 | const nestedFilePathnames = await getFilePathnames(absoluteFilePathname); 33 | allPathnames = allPathnames.concat(nestedFilePathnames); 34 | } else { 35 | allPathnames = allPathnames.concat(absoluteFilePathname); 36 | } 37 | } 38 | return allPathnames; 39 | }; 40 | 41 | export const readFile = (pathname: string) => { 42 | return fsPromises.readFile(pathname); 43 | }; 44 | 45 | const existPathname = async (pathname: string) => { 46 | try { 47 | await fsPromises.stat(pathname); 48 | return true; 49 | } catch (err) { 50 | return false; 51 | } 52 | }; 53 | 54 | const createDir = (pathname: string) => { 55 | return fsPromises.mkdir(pathname); 56 | }; 57 | 58 | const ensureWriteProcess = async (pathname: string) => { 59 | const fileDirname = path.dirname(pathname); 60 | if (await existPathname(fileDirname)) { 61 | return; 62 | } 63 | await ensureWriteProcess(fileDirname); 64 | await createDir(fileDirname); 65 | }; 66 | -------------------------------------------------------------------------------- /scripts/deploy/src/lib/s3.ts: -------------------------------------------------------------------------------- 1 | import S3 = require('aws-sdk/clients/s3'); 2 | 3 | const s3 = new S3(); 4 | 5 | export const listObjects = ( 6 | params: S3.ListObjectsV2Request, 7 | ): Promise => { 8 | return new Promise((resolve, reject) => { 9 | s3.listObjectsV2(params, (err, data) => { 10 | if (err) { 11 | reject(err); 12 | return; 13 | } 14 | if (typeof data.Contents === 'undefined') { 15 | resolve([]); 16 | return; 17 | } 18 | resolve(data.Contents); 19 | }); 20 | }); 21 | }; 22 | 23 | export const putObject = (params: S3.PutObjectRequest) => { 24 | return new Promise((resolve, reject) => { 25 | s3.putObject(params, (err, data) => { 26 | if (err) { 27 | reject(err); 28 | } else { 29 | resolve(data); 30 | } 31 | }); 32 | }); 33 | }; 34 | 35 | export const deleteObjects = (params: S3.DeleteObjectsRequest) => { 36 | return new Promise((resolve, reject) => { 37 | s3.deleteObjects(params, (err, data) => { 38 | if (err) { 39 | reject(err); 40 | } else { 41 | resolve(data); 42 | } 43 | }); 44 | }); 45 | }; 46 | -------------------------------------------------------------------------------- /scripts/deploy/src/processors/buildApp.ts: -------------------------------------------------------------------------------- 1 | import consola from 'consola'; 2 | import { spawn } from './../lib/commands'; 3 | 4 | export const buildApp = async (buildCommands: string[]) => { 5 | for (let i = 0; i < buildCommands.length; ++i) { 6 | const command = buildCommands[i]; 7 | const parsedCommand = command.split(/\s/); 8 | const commandName = parsedCommand.shift(); 9 | if (typeof commandName !== 'string' || commandName.length === 0) { 10 | consola.info(`Skip build command: \`${command}\`, index: ${i}`); 11 | continue; 12 | } 13 | await spawn(commandName, parsedCommand); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /scripts/deploy/src/processors/buildFileContext.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import minimatch from 'minimatch'; 3 | import { 4 | getFilePathnames, 5 | extractFileName, 6 | extractExtension, 7 | isDirectory, 8 | } from '../lib/file'; 9 | import { CONTENT_TYPES } from '../constants'; 10 | import { FileContext, AssetsDirContext } from 'src/types'; 11 | 12 | const selectContentType = (extension: string): string => { 13 | return extension in CONTENT_TYPES 14 | ? CONTENT_TYPES[extension] 15 | : CONTENT_TYPES['plane']; 16 | }; 17 | 18 | const buildFileContext = ({ 19 | absolutePathname, 20 | assetsDirContext, 21 | }: { 22 | absolutePathname: string; 23 | assetsDirContext: AssetsDirContext; 24 | }): FileContext => { 25 | const { pathname: dirPathname } = assetsDirContext; 26 | const { options = { prefix: '' } } = assetsDirContext; 27 | const fileName = extractFileName(absolutePathname); 28 | const extension = extractExtension(fileName); 29 | const { prefix = '' } = options; 30 | const relativePathname = absolutePathname.replace(dirPathname, ''); 31 | const s3Key = path.join(prefix, relativePathname).replace(/^\//, ''); 32 | const contentType = selectContentType(extension); 33 | return { 34 | fileName, 35 | absolutePathname, 36 | s3Key, 37 | contentType, 38 | }; 39 | }; 40 | 41 | const isMatch = ({ 42 | pathname, 43 | assetsDirContext, 44 | }: { 45 | pathname: string; 46 | assetsDirContext: AssetsDirContext; 47 | }) => { 48 | if (assetsDirContext.options == null) { 49 | return true; 50 | } 51 | const { includes = [] } = assetsDirContext.options; 52 | if (includes.length === 0) { 53 | return true; 54 | } 55 | return includes.some(match => { 56 | return minimatch(pathname, match, { matchBase: true, dot: true }); 57 | }); 58 | }; 59 | 60 | const buildFileContexts = async ( 61 | assetsDirContext: AssetsDirContext, 62 | ): Promise => { 63 | const isFile = !(await isDirectory(assetsDirContext.pathname)); 64 | const pathnames = isFile 65 | ? [assetsDirContext.pathname] 66 | : await getFilePathnames(assetsDirContext.pathname); 67 | 68 | const contexts: FileContext[] = pathnames 69 | .filter(pathname => { 70 | return isMatch({ pathname, assetsDirContext }); 71 | }) 72 | .map(pathname => { 73 | return buildFileContext({ 74 | absolutePathname: pathname, 75 | assetsDirContext, 76 | }); 77 | }); 78 | return contexts; 79 | }; 80 | 81 | export const buildFileContextsTogether = async ( 82 | assetsDirContexts: AssetsDirContext[], 83 | ): Promise => { 84 | let contexts: FileContext[] = []; 85 | for (const assetsDirContext of assetsDirContexts) { 86 | contexts = contexts.concat(await buildFileContexts(assetsDirContext)); 87 | } 88 | return contexts; 89 | }; 90 | -------------------------------------------------------------------------------- /scripts/deploy/src/processors/deleteOldObjects.ts: -------------------------------------------------------------------------------- 1 | import consola from 'consola'; 2 | import dayjs from 'dayjs'; 3 | import { listObjects, deleteObjects } from '../lib/s3'; 4 | import { S3Bucket, S3ObjectContext } from 'src/types'; 5 | 6 | const buildLastModified = (lastModified: Date | undefined): Date => { 7 | if (typeof lastModified === 'undefined') { 8 | return new Date(0); 9 | } 10 | return lastModified; 11 | }; 12 | 13 | const listS3Objects = async ({ s3Bucket }: { s3Bucket: S3Bucket }) => { 14 | const objects = await listObjects({ Bucket: s3Bucket.name }); 15 | return objects.map(({ Key, LastModified }) => ({ 16 | key: Key || '', 17 | lastModified: buildLastModified(LastModified), 18 | })); 19 | }; 20 | 21 | const isObjectToDelete = (s3ObjectContext: S3ObjectContext) => { 22 | const { lastModified } = s3ObjectContext; 23 | const currentDate = dayjs(new Date()); 24 | const modifiedDate = dayjs(lastModified); 25 | return currentDate.diff(modifiedDate, 'day') > 7; 26 | }; 27 | 28 | const deleteS3Objects = async ({ 29 | s3Bucket, 30 | objectsToDelete, 31 | }: { 32 | s3Bucket: S3Bucket; 33 | objectsToDelete: S3ObjectContext[]; 34 | }): Promise => { 35 | const objects = objectsToDelete.map(({ key }) => ({ Key: key })); 36 | await deleteObjects({ 37 | Bucket: s3Bucket.name, 38 | Delete: { 39 | Objects: objects, 40 | }, 41 | }); 42 | objectsToDelete.forEach(({ key }) => consola.success(`Deleted: ${key}`)); 43 | }; 44 | 45 | type deleteOldObjects = (params: { s3Bucket: S3Bucket }) => Promise; 46 | 47 | export const deleteOldObjects: deleteOldObjects = async ({ s3Bucket }) => { 48 | const objects = await listS3Objects({ s3Bucket }); 49 | const objectsToDelete = objects.filter(isObjectToDelete); 50 | if (objectsToDelete.length === 0) { 51 | consola.info('There is no old object.'); 52 | return; 53 | } 54 | await deleteS3Objects({ s3Bucket, objectsToDelete }); 55 | }; 56 | -------------------------------------------------------------------------------- /scripts/deploy/src/processors/deployApp.ts: -------------------------------------------------------------------------------- 1 | import { spawn } from './../lib/commands'; 2 | 3 | export const deployApp = () => { 4 | return spawn('yarn', ['sls:deploy']); 5 | }; 6 | -------------------------------------------------------------------------------- /scripts/deploy/src/processors/deployAssets.ts: -------------------------------------------------------------------------------- 1 | import { S3 } from 'aws-sdk'; 2 | import consola from 'consola'; 3 | import path from 'path'; 4 | 5 | import { putObject } from '../lib/s3'; 6 | import { readFile } from '../lib/file'; 7 | import { FileContext, S3Bucket, DeployConfig } from 'src/types'; 8 | 9 | const buildKey = ({ 10 | prefix = '', 11 | relativePathname, 12 | }: { 13 | prefix?: string; 14 | relativePathname: string; 15 | }) => { 16 | const key = path.join(prefix, relativePathname); 17 | return key.replace(/^\//, ''); 18 | }; 19 | 20 | const createCacheControlBuilder = ( 21 | deployConfig: DeployConfig, 22 | ): ((fileContext: FileContext) => string) => { 23 | const { cacheControl } = deployConfig; 24 | if (typeof cacheControl === 'function') { 25 | return cacheControl; 26 | } 27 | return () => cacheControl; 28 | }; 29 | 30 | const buildParams = async ({ 31 | fileContext, 32 | s3Bucket, 33 | cacheControlBuilder, 34 | }: { 35 | fileContext: FileContext; 36 | s3Bucket: S3Bucket; 37 | cacheControlBuilder: (fileContext: FileContext) => string; 38 | }): Promise => { 39 | const body = await readFile(fileContext.absolutePathname); 40 | return { 41 | Bucket: s3Bucket.name, 42 | Key: buildKey({ 43 | prefix: s3Bucket.prefix, 44 | relativePathname: fileContext.s3Key, 45 | }), 46 | Body: body, 47 | ContentType: fileContext.contentType, 48 | CacheControl: cacheControlBuilder(fileContext), 49 | }; 50 | }; 51 | 52 | type deployAssets = (params: { 53 | fileContexts: FileContext[]; 54 | s3Bucket: S3Bucket; 55 | deployConifg: DeployConfig; 56 | }) => Promise; 57 | 58 | export const deployAssets: deployAssets = async ({ 59 | fileContexts, 60 | s3Bucket, 61 | deployConifg, 62 | }) => { 63 | const cacheControlBuilder = createCacheControlBuilder(deployConifg); 64 | 65 | for (const fileContext of fileContexts) { 66 | const params = await buildParams({ 67 | fileContext, 68 | s3Bucket, 69 | cacheControlBuilder, 70 | }); 71 | await putObject(params); 72 | consola.success(`Deployed: ${fileContext.s3Key}`); 73 | } 74 | return; 75 | }; 76 | -------------------------------------------------------------------------------- /scripts/deploy/src/processors/index.ts: -------------------------------------------------------------------------------- 1 | export * from './buildFileContext'; 2 | export * from './deployAssets'; 3 | export * from './deleteOldObjects'; 4 | export * from './buildApp'; 5 | export * from './deployApp'; 6 | export * from './purgeCDN'; 7 | -------------------------------------------------------------------------------- /scripts/deploy/src/processors/purgeCDN.ts: -------------------------------------------------------------------------------- 1 | import consola from 'consola'; 2 | import { createInvalidation } from './../lib/cloudFront'; 3 | 4 | export const purgeCDN = async ({ 5 | cloudFrontId, 6 | items = ['/*'], 7 | }: { 8 | cloudFrontId: string; 9 | items?: string[]; 10 | }): Promise => { 11 | consola.info('Start purging CDN'); 12 | await createInvalidation({ 13 | DistributionId: cloudFrontId, 14 | InvalidationBatch: { 15 | CallerReference: String(new Date().getTime()), 16 | Paths: { 17 | Quantity: 1, 18 | Items: items, 19 | }, 20 | }, 21 | }); 22 | consola.success('Succeeded in purging CDN'); 23 | }; 24 | -------------------------------------------------------------------------------- /scripts/deploy/src/types/config.type.ts: -------------------------------------------------------------------------------- 1 | import { AssetsDirContext, FileContext } from './contexts.type'; 2 | 3 | export interface S3Bucket { 4 | name: string; 5 | prefix?: string; 6 | } 7 | 8 | export interface DeployConfig { 9 | assetsDirs: AssetsDirContext[]; 10 | s3Bucket: S3Bucket; 11 | cloudFrontId: string; 12 | buildCommands: string[]; 13 | cacheControl: string | ((fileContext: FileContext) => string); 14 | } 15 | -------------------------------------------------------------------------------- /scripts/deploy/src/types/contexts.type.ts: -------------------------------------------------------------------------------- 1 | export interface FileContext { 2 | fileName: string; 3 | absolutePathname: string; 4 | s3Key: string; 5 | contentType: string; 6 | } 7 | 8 | export interface AssetsDirContext { 9 | pathname: string; 10 | options?: { 11 | prefix?: string; 12 | includes?: string[]; 13 | }; 14 | } 15 | 16 | export interface S3ObjectContext { 17 | key: string; 18 | lastModified: Date; 19 | } 20 | -------------------------------------------------------------------------------- /scripts/deploy/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './config.type'; 2 | export * from './contexts.type'; 3 | -------------------------------------------------------------------------------- /scripts/deploy/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 4 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 5 | "lib": ["es5"], /* Specify library files to be included in the compilation. */ 6 | "types": ["node"], 7 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 8 | "outDir": "./dist", /* Redirect output structure to the directory. */ 9 | "removeComments": true, /* Do not emit comments to output. */ 10 | "moduleResolution": "node", 11 | 12 | /* Strict Type-Checking Options */ 13 | "strict": true, /* Enable all strict type-checking options. */ 14 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 15 | // "strictNullChecks": true, /* Enable strict null checks. */ 16 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 17 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 18 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 19 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 20 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 21 | 22 | /* Additional Checks */ 23 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 24 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 25 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 26 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 27 | 28 | /* Module Resolution Options */ 29 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 30 | "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 31 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 32 | // "typeRoots": [], /* List of folders to include type definitions from. */ 33 | // "types": [], /* Type declaration files to be included in compilation. */ 34 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 35 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 36 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 37 | 38 | /* Source Map Options */ 39 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 40 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 41 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 42 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 43 | 44 | /* Experimental Options */ 45 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 46 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 47 | }, 48 | "include": ["src/**/*.ts"], 49 | "exclude": ["node_modules"] 50 | } 51 | -------------------------------------------------------------------------------- /scripts/deploy/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.0.0" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" 8 | integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== 9 | dependencies: 10 | "@babel/highlight" "^7.0.0" 11 | 12 | "@babel/highlight@^7.0.0": 13 | version "7.0.0" 14 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" 15 | integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== 16 | dependencies: 17 | chalk "^2.0.0" 18 | esutils "^2.0.2" 19 | js-tokens "^4.0.0" 20 | 21 | "@types/cross-spawn@^6.0.0": 22 | version "6.0.0" 23 | resolved "https://registry.yarnpkg.com/@types/cross-spawn/-/cross-spawn-6.0.0.tgz#320aaf1d1a12979f1b84fe7a5590a7e860bf3a80" 24 | integrity sha512-evp2ZGsFw9YKprDbg8ySgC9NA15g3YgiI8ANkGmKKvvi0P2aDGYLPxQIC5qfeKNUOe3TjABVGuah6omPRpIYhg== 25 | dependencies: 26 | "@types/node" "*" 27 | 28 | "@types/eslint-visitor-keys@^1.0.0": 29 | version "1.0.0" 30 | resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" 31 | integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== 32 | 33 | "@types/node@*", "@types/node@^12.0.10": 34 | version "12.0.10" 35 | resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.10.tgz#51babf9c7deadd5343620055fc8aff7995c8b031" 36 | integrity sha512-LcsGbPomWsad6wmMNv7nBLw7YYYyfdYcz6xryKYQhx89c3XXan+8Q6AJ43G5XDIaklaVkK3mE4fCb0SBvMiPSQ== 37 | 38 | "@typescript-eslint/eslint-plugin@^1.10.2": 39 | version "1.10.2" 40 | resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.10.2.tgz#552fc64cfcb19c6162190360217c945e8faa330a" 41 | integrity sha512-7449RhjE1oLFIy5E/5rT4wG5+KsfPzakJuhvpzXJ3C46lq7xywY0/Rjo9ZBcwrfbk0nRZ5xmUHkk7DZ67tSBKw== 42 | dependencies: 43 | "@typescript-eslint/experimental-utils" "1.10.2" 44 | eslint-utils "^1.3.1" 45 | functional-red-black-tree "^1.0.1" 46 | regexpp "^2.0.1" 47 | tsutils "^3.7.0" 48 | 49 | "@typescript-eslint/experimental-utils@1.10.2": 50 | version "1.10.2" 51 | resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-1.10.2.tgz#cd548c03fc1a2b3ba5c136d1599001a1ede24215" 52 | integrity sha512-Hf5lYcrnTH5Oc67SRrQUA7KuHErMvCf5RlZsyxXPIT6AXa8fKTyfFO6vaEnUmlz48RpbxO4f0fY3QtWkuHZNjg== 53 | dependencies: 54 | "@typescript-eslint/typescript-estree" "1.10.2" 55 | eslint-scope "^4.0.0" 56 | 57 | "@typescript-eslint/parser@^1.10.2": 58 | version "1.10.2" 59 | resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-1.10.2.tgz#36cfe8c6bf1b6c1dd81da56f88c8588f4b1a852b" 60 | integrity sha512-xWDWPfZfV0ENU17ermIUVEVSseBBJxKfqBcRCMZ8nAjJbfA5R7NWMZmFFHYnars5MjK4fPjhu4gwQv526oZIPQ== 61 | dependencies: 62 | "@types/eslint-visitor-keys" "^1.0.0" 63 | "@typescript-eslint/experimental-utils" "1.10.2" 64 | "@typescript-eslint/typescript-estree" "1.10.2" 65 | eslint-visitor-keys "^1.0.0" 66 | 67 | "@typescript-eslint/typescript-estree@1.10.2": 68 | version "1.10.2" 69 | resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-1.10.2.tgz#8403585dd74b6cfb6f78aa98b6958de158b5897b" 70 | integrity sha512-Kutjz0i69qraOsWeI8ETqYJ07tRLvD9URmdrMoF10bG8y8ucLmPtSxROvVejWvlJUGl2et/plnMiKRDW+rhEhw== 71 | dependencies: 72 | lodash.unescape "4.0.1" 73 | semver "5.5.0" 74 | 75 | acorn-jsx@^5.0.0: 76 | version "5.0.1" 77 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" 78 | integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== 79 | 80 | acorn@^6.0.7: 81 | version "6.4.1" 82 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" 83 | integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== 84 | 85 | ajv@^6.10.0, ajv@^6.9.1: 86 | version "6.10.0" 87 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" 88 | integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== 89 | dependencies: 90 | fast-deep-equal "^2.0.1" 91 | fast-json-stable-stringify "^2.0.0" 92 | json-schema-traverse "^0.4.1" 93 | uri-js "^4.2.2" 94 | 95 | ansi-escapes@^3.2.0: 96 | version "3.2.0" 97 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" 98 | integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== 99 | 100 | ansi-regex@^3.0.0: 101 | version "3.0.0" 102 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 103 | integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= 104 | 105 | ansi-regex@^4.1.0: 106 | version "4.1.0" 107 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" 108 | integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== 109 | 110 | ansi-styles@^3.2.0, ansi-styles@^3.2.1: 111 | version "3.2.1" 112 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 113 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 114 | dependencies: 115 | color-convert "^1.9.0" 116 | 117 | argparse@^1.0.7: 118 | version "1.0.10" 119 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 120 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 121 | dependencies: 122 | sprintf-js "~1.0.2" 123 | 124 | astral-regex@^1.0.0: 125 | version "1.0.0" 126 | resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" 127 | integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== 128 | 129 | aws-sdk@^2.480.0: 130 | version "2.480.0" 131 | resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.480.0.tgz#ab4bb7ad2f4372fa5aa1051fc1553e82d34b27ca" 132 | integrity sha512-X6xOgBeg8ZZJPnL4/wHXFIP6QF2SBABqw/F5l5zT/vEPUfmrIg24LVSUwPXmV6ZMh4hwsuuOjO910MbjNoHXXg== 133 | dependencies: 134 | buffer "4.9.1" 135 | events "1.1.1" 136 | ieee754 "1.1.8" 137 | jmespath "0.15.0" 138 | querystring "0.2.0" 139 | sax "1.2.1" 140 | url "0.10.3" 141 | uuid "3.3.2" 142 | xml2js "0.4.19" 143 | 144 | balanced-match@^1.0.0: 145 | version "1.0.0" 146 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 147 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 148 | 149 | base64-js@^1.0.2: 150 | version "1.3.0" 151 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" 152 | integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== 153 | 154 | brace-expansion@^1.1.7: 155 | version "1.1.11" 156 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 157 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 158 | dependencies: 159 | balanced-match "^1.0.0" 160 | concat-map "0.0.1" 161 | 162 | buffer@4.9.1: 163 | version "4.9.1" 164 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" 165 | integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= 166 | dependencies: 167 | base64-js "^1.0.2" 168 | ieee754 "^1.1.4" 169 | isarray "^1.0.0" 170 | 171 | callsites@^3.0.0: 172 | version "3.1.0" 173 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 174 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 175 | 176 | chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: 177 | version "2.4.2" 178 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 179 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 180 | dependencies: 181 | ansi-styles "^3.2.1" 182 | escape-string-regexp "^1.0.5" 183 | supports-color "^5.3.0" 184 | 185 | chardet@^0.7.0: 186 | version "0.7.0" 187 | resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" 188 | integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== 189 | 190 | cli-cursor@^2.1.0: 191 | version "2.1.0" 192 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" 193 | integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= 194 | dependencies: 195 | restore-cursor "^2.0.0" 196 | 197 | cli-width@^2.0.0: 198 | version "2.2.0" 199 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" 200 | integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= 201 | 202 | color-convert@^1.9.0: 203 | version "1.9.3" 204 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 205 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 206 | dependencies: 207 | color-name "1.1.3" 208 | 209 | color-name@1.1.3: 210 | version "1.1.3" 211 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 212 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 213 | 214 | concat-map@0.0.1: 215 | version "0.0.1" 216 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 217 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 218 | 219 | consola@^2.9.0: 220 | version "2.9.0" 221 | resolved "https://registry.yarnpkg.com/consola/-/consola-2.9.0.tgz#57760e3a65a53ec27337f4add31505802d902278" 222 | integrity sha512-34Iue+LRcWbndFIfZc5boNizWlsrRjqIBJZTe591vImgbnq7nx2EzlrLtANj9TH2Fxm7puFJBJAOk5BhvZOddQ== 223 | 224 | cross-spawn@^6.0.5: 225 | version "6.0.5" 226 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" 227 | integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== 228 | dependencies: 229 | nice-try "^1.0.4" 230 | path-key "^2.0.1" 231 | semver "^5.5.0" 232 | shebang-command "^1.2.0" 233 | which "^1.2.9" 234 | 235 | dayjs@^1.8.14: 236 | version "1.8.14" 237 | resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.14.tgz#43e4f62830c2c3342c3fcd25934dc9162dbe6f38" 238 | integrity sha512-AVhDmRTe541iWirnoeFSSDDGvCT6HWaNQ4z2WmmzXMGZj6ph6ydao2teKq/eUtR43GPJXlYFD+C/SotG1P9wUQ== 239 | 240 | debug@^4.0.1: 241 | version "4.1.1" 242 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" 243 | integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== 244 | dependencies: 245 | ms "^2.1.1" 246 | 247 | deep-is@~0.1.3: 248 | version "0.1.3" 249 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" 250 | integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= 251 | 252 | doctrine@^3.0.0: 253 | version "3.0.0" 254 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" 255 | integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== 256 | dependencies: 257 | esutils "^2.0.2" 258 | 259 | emoji-regex@^7.0.1: 260 | version "7.0.3" 261 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" 262 | integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== 263 | 264 | escape-string-regexp@^1.0.5: 265 | version "1.0.5" 266 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 267 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 268 | 269 | eslint-config-prettier@^5.0.0: 270 | version "5.0.0" 271 | resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-5.0.0.tgz#f7a94b2b8ae7cbf25842c36fa96c6d32cd0a697c" 272 | integrity sha512-c17Aqiz5e8LEqoc/QPmYnaxQFAHTx2KlCZBPxXXjEMmNchOLnV/7j0HoPZuC+rL/tDC9bazUYOKJW9bOhftI/w== 273 | dependencies: 274 | get-stdin "^6.0.0" 275 | 276 | eslint-plugin-prettier@^3.1.0: 277 | version "3.1.0" 278 | resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.0.tgz#8695188f95daa93b0dc54b249347ca3b79c4686d" 279 | integrity sha512-XWX2yVuwVNLOUhQijAkXz+rMPPoCr7WFiAl8ig6I7Xn+pPVhDhzg4DxHpmbeb0iqjO9UronEA3Tb09ChnFVHHA== 280 | dependencies: 281 | prettier-linter-helpers "^1.0.0" 282 | 283 | eslint-scope@^4.0.0, eslint-scope@^4.0.3: 284 | version "4.0.3" 285 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" 286 | integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== 287 | dependencies: 288 | esrecurse "^4.1.0" 289 | estraverse "^4.1.1" 290 | 291 | eslint-utils@^1.3.1: 292 | version "1.4.2" 293 | resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" 294 | integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== 295 | dependencies: 296 | eslint-visitor-keys "^1.0.0" 297 | 298 | eslint-visitor-keys@^1.0.0: 299 | version "1.1.0" 300 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" 301 | integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== 302 | 303 | eslint@^6.0.0: 304 | version "6.0.0" 305 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.0.0.tgz#9223f19223de73b4ed730e11bff44a376b65844d" 306 | integrity sha512-SrrIfcd4tOgsspOKTSwamuTOAMZOUigHQhVMrzNjz4/B9Za6SHQDIocMIyIDfwDgx6MhS15nS6HC8kumCV2qBQ== 307 | dependencies: 308 | "@babel/code-frame" "^7.0.0" 309 | ajv "^6.10.0" 310 | chalk "^2.1.0" 311 | cross-spawn "^6.0.5" 312 | debug "^4.0.1" 313 | doctrine "^3.0.0" 314 | eslint-scope "^4.0.3" 315 | eslint-utils "^1.3.1" 316 | eslint-visitor-keys "^1.0.0" 317 | espree "^6.0.0" 318 | esquery "^1.0.1" 319 | esutils "^2.0.2" 320 | file-entry-cache "^5.0.1" 321 | functional-red-black-tree "^1.0.1" 322 | glob-parent "^3.1.0" 323 | globals "^11.7.0" 324 | ignore "^4.0.6" 325 | import-fresh "^3.0.0" 326 | imurmurhash "^0.1.4" 327 | inquirer "^6.2.2" 328 | is-glob "^4.0.0" 329 | js-yaml "^3.13.1" 330 | json-stable-stringify-without-jsonify "^1.0.1" 331 | levn "^0.3.0" 332 | lodash "^4.17.11" 333 | minimatch "^3.0.4" 334 | mkdirp "^0.5.1" 335 | natural-compare "^1.4.0" 336 | optionator "^0.8.2" 337 | progress "^2.0.0" 338 | regexpp "^2.0.1" 339 | semver "^5.5.1" 340 | strip-ansi "^4.0.0" 341 | strip-json-comments "^2.0.1" 342 | table "^5.2.3" 343 | text-table "^0.2.0" 344 | 345 | espree@^6.0.0: 346 | version "6.0.0" 347 | resolved "https://registry.yarnpkg.com/espree/-/espree-6.0.0.tgz#716fc1f5a245ef5b9a7fdb1d7b0d3f02322e75f6" 348 | integrity sha512-lJvCS6YbCn3ImT3yKkPe0+tJ+mH6ljhGNjHQH9mRtiO6gjhVAOhVXW1yjnwqGwTkK3bGbye+hb00nFNmu0l/1Q== 349 | dependencies: 350 | acorn "^6.0.7" 351 | acorn-jsx "^5.0.0" 352 | eslint-visitor-keys "^1.0.0" 353 | 354 | esprima@^4.0.0: 355 | version "4.0.1" 356 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 357 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 358 | 359 | esquery@^1.0.1: 360 | version "1.0.1" 361 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" 362 | integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== 363 | dependencies: 364 | estraverse "^4.0.0" 365 | 366 | esrecurse@^4.1.0: 367 | version "4.2.1" 368 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" 369 | integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== 370 | dependencies: 371 | estraverse "^4.1.0" 372 | 373 | estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: 374 | version "4.2.0" 375 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" 376 | integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= 377 | 378 | esutils@^2.0.2: 379 | version "2.0.2" 380 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" 381 | integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= 382 | 383 | events@1.1.1: 384 | version "1.1.1" 385 | resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" 386 | integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= 387 | 388 | external-editor@^3.0.3: 389 | version "3.0.3" 390 | resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" 391 | integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== 392 | dependencies: 393 | chardet "^0.7.0" 394 | iconv-lite "^0.4.24" 395 | tmp "^0.0.33" 396 | 397 | fast-deep-equal@^2.0.1: 398 | version "2.0.1" 399 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" 400 | integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= 401 | 402 | fast-diff@^1.1.2: 403 | version "1.2.0" 404 | resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" 405 | integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== 406 | 407 | fast-json-stable-stringify@^2.0.0: 408 | version "2.0.0" 409 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" 410 | integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= 411 | 412 | fast-levenshtein@~2.0.4: 413 | version "2.0.6" 414 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 415 | integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= 416 | 417 | figures@^2.0.0: 418 | version "2.0.0" 419 | resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" 420 | integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= 421 | dependencies: 422 | escape-string-regexp "^1.0.5" 423 | 424 | file-entry-cache@^5.0.1: 425 | version "5.0.1" 426 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" 427 | integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== 428 | dependencies: 429 | flat-cache "^2.0.1" 430 | 431 | flat-cache@^2.0.1: 432 | version "2.0.1" 433 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" 434 | integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== 435 | dependencies: 436 | flatted "^2.0.0" 437 | rimraf "2.6.3" 438 | write "1.0.3" 439 | 440 | flatted@^2.0.0: 441 | version "2.0.0" 442 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" 443 | integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== 444 | 445 | fs.realpath@^1.0.0: 446 | version "1.0.0" 447 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 448 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 449 | 450 | functional-red-black-tree@^1.0.1: 451 | version "1.0.1" 452 | resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" 453 | integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= 454 | 455 | get-stdin@^6.0.0: 456 | version "6.0.0" 457 | resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" 458 | integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== 459 | 460 | glob-parent@^3.1.0: 461 | version "3.1.0" 462 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" 463 | integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= 464 | dependencies: 465 | is-glob "^3.1.0" 466 | path-dirname "^1.0.0" 467 | 468 | glob@^7.1.3: 469 | version "7.1.4" 470 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" 471 | integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== 472 | dependencies: 473 | fs.realpath "^1.0.0" 474 | inflight "^1.0.4" 475 | inherits "2" 476 | minimatch "^3.0.4" 477 | once "^1.3.0" 478 | path-is-absolute "^1.0.0" 479 | 480 | globals@^11.7.0: 481 | version "11.12.0" 482 | resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" 483 | integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== 484 | 485 | has-flag@^3.0.0: 486 | version "3.0.0" 487 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 488 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 489 | 490 | iconv-lite@^0.4.24: 491 | version "0.4.24" 492 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 493 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 494 | dependencies: 495 | safer-buffer ">= 2.1.2 < 3" 496 | 497 | ieee754@1.1.8: 498 | version "1.1.8" 499 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" 500 | integrity sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q= 501 | 502 | ieee754@^1.1.4: 503 | version "1.1.13" 504 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" 505 | integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== 506 | 507 | ignore@^4.0.6: 508 | version "4.0.6" 509 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" 510 | integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== 511 | 512 | import-fresh@^3.0.0: 513 | version "3.0.0" 514 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" 515 | integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== 516 | dependencies: 517 | parent-module "^1.0.0" 518 | resolve-from "^4.0.0" 519 | 520 | imurmurhash@^0.1.4: 521 | version "0.1.4" 522 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 523 | integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= 524 | 525 | inflight@^1.0.4: 526 | version "1.0.6" 527 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 528 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 529 | dependencies: 530 | once "^1.3.0" 531 | wrappy "1" 532 | 533 | inherits@2: 534 | version "2.0.4" 535 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 536 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 537 | 538 | inquirer@^6.2.2: 539 | version "6.4.1" 540 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.4.1.tgz#7bd9e5ab0567cd23b41b0180b68e0cfa82fc3c0b" 541 | integrity sha512-/Jw+qPZx4EDYsaT6uz7F4GJRNFMRdKNeUZw3ZnKV8lyuUgz/YWRCSUAJMZSVhSq4Ec0R2oYnyi6b3d4JXcL5Nw== 542 | dependencies: 543 | ansi-escapes "^3.2.0" 544 | chalk "^2.4.2" 545 | cli-cursor "^2.1.0" 546 | cli-width "^2.0.0" 547 | external-editor "^3.0.3" 548 | figures "^2.0.0" 549 | lodash "^4.17.11" 550 | mute-stream "0.0.7" 551 | run-async "^2.2.0" 552 | rxjs "^6.4.0" 553 | string-width "^2.1.0" 554 | strip-ansi "^5.1.0" 555 | through "^2.3.6" 556 | 557 | is-extglob@^2.1.0, is-extglob@^2.1.1: 558 | version "2.1.1" 559 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 560 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 561 | 562 | is-fullwidth-code-point@^2.0.0: 563 | version "2.0.0" 564 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 565 | integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= 566 | 567 | is-glob@^3.1.0: 568 | version "3.1.0" 569 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" 570 | integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= 571 | dependencies: 572 | is-extglob "^2.1.0" 573 | 574 | is-glob@^4.0.0: 575 | version "4.0.1" 576 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" 577 | integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== 578 | dependencies: 579 | is-extglob "^2.1.1" 580 | 581 | is-promise@^2.1.0: 582 | version "2.1.0" 583 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" 584 | integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= 585 | 586 | isarray@^1.0.0: 587 | version "1.0.0" 588 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 589 | integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= 590 | 591 | isexe@^2.0.0: 592 | version "2.0.0" 593 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 594 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 595 | 596 | jmespath@0.15.0: 597 | version "0.15.0" 598 | resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" 599 | integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc= 600 | 601 | js-tokens@^4.0.0: 602 | version "4.0.0" 603 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 604 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 605 | 606 | js-yaml@^3.13.1: 607 | version "3.13.1" 608 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" 609 | integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== 610 | dependencies: 611 | argparse "^1.0.7" 612 | esprima "^4.0.0" 613 | 614 | json-schema-traverse@^0.4.1: 615 | version "0.4.1" 616 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 617 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 618 | 619 | json-stable-stringify-without-jsonify@^1.0.1: 620 | version "1.0.1" 621 | resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" 622 | integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= 623 | 624 | levn@^0.3.0, levn@~0.3.0: 625 | version "0.3.0" 626 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" 627 | integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= 628 | dependencies: 629 | prelude-ls "~1.1.2" 630 | type-check "~0.3.2" 631 | 632 | lodash.unescape@4.0.1: 633 | version "4.0.1" 634 | resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" 635 | integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= 636 | 637 | lodash@^4.17.11: 638 | version "4.17.14" 639 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" 640 | integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== 641 | 642 | mimic-fn@^1.0.0: 643 | version "1.2.0" 644 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" 645 | integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== 646 | 647 | minimatch@^3.0.4: 648 | version "3.0.4" 649 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 650 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 651 | dependencies: 652 | brace-expansion "^1.1.7" 653 | 654 | minimist@0.0.8: 655 | version "0.0.8" 656 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 657 | integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= 658 | 659 | mkdirp@^0.5.1: 660 | version "0.5.1" 661 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 662 | integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= 663 | dependencies: 664 | minimist "0.0.8" 665 | 666 | ms@^2.1.1: 667 | version "2.1.2" 668 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 669 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 670 | 671 | mute-stream@0.0.7: 672 | version "0.0.7" 673 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" 674 | integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= 675 | 676 | natural-compare@^1.4.0: 677 | version "1.4.0" 678 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 679 | integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= 680 | 681 | nice-try@^1.0.4: 682 | version "1.0.5" 683 | resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" 684 | integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== 685 | 686 | once@^1.3.0: 687 | version "1.4.0" 688 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 689 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 690 | dependencies: 691 | wrappy "1" 692 | 693 | onetime@^2.0.0: 694 | version "2.0.1" 695 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" 696 | integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= 697 | dependencies: 698 | mimic-fn "^1.0.0" 699 | 700 | optionator@^0.8.2: 701 | version "0.8.2" 702 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" 703 | integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= 704 | dependencies: 705 | deep-is "~0.1.3" 706 | fast-levenshtein "~2.0.4" 707 | levn "~0.3.0" 708 | prelude-ls "~1.1.2" 709 | type-check "~0.3.2" 710 | wordwrap "~1.0.0" 711 | 712 | os-tmpdir@~1.0.2: 713 | version "1.0.2" 714 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 715 | integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= 716 | 717 | parent-module@^1.0.0: 718 | version "1.0.1" 719 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" 720 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 721 | dependencies: 722 | callsites "^3.0.0" 723 | 724 | path-dirname@^1.0.0: 725 | version "1.0.2" 726 | resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" 727 | integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= 728 | 729 | path-is-absolute@^1.0.0: 730 | version "1.0.1" 731 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 732 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 733 | 734 | path-key@^2.0.1: 735 | version "2.0.1" 736 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 737 | integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= 738 | 739 | prelude-ls@~1.1.2: 740 | version "1.1.2" 741 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" 742 | integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= 743 | 744 | prettier-linter-helpers@^1.0.0: 745 | version "1.0.0" 746 | resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" 747 | integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== 748 | dependencies: 749 | fast-diff "^1.1.2" 750 | 751 | prettier@^1.18.2: 752 | version "1.18.2" 753 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" 754 | integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== 755 | 756 | progress@^2.0.0: 757 | version "2.0.3" 758 | resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" 759 | integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== 760 | 761 | punycode@1.3.2: 762 | version "1.3.2" 763 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" 764 | integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= 765 | 766 | punycode@^2.1.0: 767 | version "2.1.1" 768 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 769 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 770 | 771 | querystring@0.2.0: 772 | version "0.2.0" 773 | resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" 774 | integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= 775 | 776 | regexpp@^2.0.1: 777 | version "2.0.1" 778 | resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" 779 | integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== 780 | 781 | resolve-from@^4.0.0: 782 | version "4.0.0" 783 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 784 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 785 | 786 | restore-cursor@^2.0.0: 787 | version "2.0.0" 788 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" 789 | integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= 790 | dependencies: 791 | onetime "^2.0.0" 792 | signal-exit "^3.0.2" 793 | 794 | rimraf@2.6.3: 795 | version "2.6.3" 796 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" 797 | integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== 798 | dependencies: 799 | glob "^7.1.3" 800 | 801 | run-async@^2.2.0: 802 | version "2.3.0" 803 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" 804 | integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= 805 | dependencies: 806 | is-promise "^2.1.0" 807 | 808 | rxjs@^6.4.0: 809 | version "6.5.2" 810 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7" 811 | integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg== 812 | dependencies: 813 | tslib "^1.9.0" 814 | 815 | "safer-buffer@>= 2.1.2 < 3": 816 | version "2.1.2" 817 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 818 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 819 | 820 | sax@1.2.1: 821 | version "1.2.1" 822 | resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" 823 | integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= 824 | 825 | sax@>=0.6.0: 826 | version "1.2.4" 827 | resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" 828 | integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== 829 | 830 | semver@5.5.0: 831 | version "5.5.0" 832 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" 833 | integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== 834 | 835 | semver@^5.5.0, semver@^5.5.1: 836 | version "5.7.0" 837 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" 838 | integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== 839 | 840 | shebang-command@^1.2.0: 841 | version "1.2.0" 842 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 843 | integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= 844 | dependencies: 845 | shebang-regex "^1.0.0" 846 | 847 | shebang-regex@^1.0.0: 848 | version "1.0.0" 849 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 850 | integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= 851 | 852 | signal-exit@^3.0.2: 853 | version "3.0.2" 854 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 855 | integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= 856 | 857 | slice-ansi@^2.1.0: 858 | version "2.1.0" 859 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" 860 | integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== 861 | dependencies: 862 | ansi-styles "^3.2.0" 863 | astral-regex "^1.0.0" 864 | is-fullwidth-code-point "^2.0.0" 865 | 866 | sprintf-js@~1.0.2: 867 | version "1.0.3" 868 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 869 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 870 | 871 | string-width@^2.1.0: 872 | version "2.1.1" 873 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 874 | integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 875 | dependencies: 876 | is-fullwidth-code-point "^2.0.0" 877 | strip-ansi "^4.0.0" 878 | 879 | string-width@^3.0.0: 880 | version "3.1.0" 881 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" 882 | integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== 883 | dependencies: 884 | emoji-regex "^7.0.1" 885 | is-fullwidth-code-point "^2.0.0" 886 | strip-ansi "^5.1.0" 887 | 888 | strip-ansi@^4.0.0: 889 | version "4.0.0" 890 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 891 | integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= 892 | dependencies: 893 | ansi-regex "^3.0.0" 894 | 895 | strip-ansi@^5.1.0: 896 | version "5.2.0" 897 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" 898 | integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== 899 | dependencies: 900 | ansi-regex "^4.1.0" 901 | 902 | strip-json-comments@^2.0.1: 903 | version "2.0.1" 904 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 905 | integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= 906 | 907 | supports-color@^5.3.0: 908 | version "5.5.0" 909 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 910 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 911 | dependencies: 912 | has-flag "^3.0.0" 913 | 914 | table@^5.2.3: 915 | version "5.4.1" 916 | resolved "https://registry.yarnpkg.com/table/-/table-5.4.1.tgz#0691ae2ebe8259858efb63e550b6d5f9300171e8" 917 | integrity sha512-E6CK1/pZe2N75rGZQotFOdmzWQ1AILtgYbMAbAjvms0S1l5IDB47zG3nCnFGB/w+7nB3vKofbLXCH7HPBo864w== 918 | dependencies: 919 | ajv "^6.9.1" 920 | lodash "^4.17.11" 921 | slice-ansi "^2.1.0" 922 | string-width "^3.0.0" 923 | 924 | text-table@^0.2.0: 925 | version "0.2.0" 926 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 927 | integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= 928 | 929 | through@^2.3.6: 930 | version "2.3.8" 931 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 932 | integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= 933 | 934 | tmp@^0.0.33: 935 | version "0.0.33" 936 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" 937 | integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== 938 | dependencies: 939 | os-tmpdir "~1.0.2" 940 | 941 | tslib@^1.8.1, tslib@^1.9.0: 942 | version "1.10.0" 943 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" 944 | integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== 945 | 946 | tsutils@^3.7.0: 947 | version "3.14.0" 948 | resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.14.0.tgz#bf8d5a7bae5369331fa0f2b0a5a10bd7f7396c77" 949 | integrity sha512-SmzGbB0l+8I0QwsPgjooFRaRvHLBLNYM8SeQ0k6rtNDru5sCGeLJcZdwilNndN+GysuFjF5EIYgN8GfFG6UeUw== 950 | dependencies: 951 | tslib "^1.8.1" 952 | 953 | type-check@~0.3.2: 954 | version "0.3.2" 955 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" 956 | integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= 957 | dependencies: 958 | prelude-ls "~1.1.2" 959 | 960 | typescript@^3.5.2: 961 | version "3.5.2" 962 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.2.tgz#a09e1dc69bc9551cadf17dba10ee42cf55e5d56c" 963 | integrity sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA== 964 | 965 | uri-js@^4.2.2: 966 | version "4.2.2" 967 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" 968 | integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== 969 | dependencies: 970 | punycode "^2.1.0" 971 | 972 | url@0.10.3: 973 | version "0.10.3" 974 | resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" 975 | integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ= 976 | dependencies: 977 | punycode "1.3.2" 978 | querystring "0.2.0" 979 | 980 | uuid@3.3.2: 981 | version "3.3.2" 982 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" 983 | integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== 984 | 985 | which@^1.2.9: 986 | version "1.3.1" 987 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 988 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 989 | dependencies: 990 | isexe "^2.0.0" 991 | 992 | wordwrap@~1.0.0: 993 | version "1.0.0" 994 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" 995 | integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= 996 | 997 | wrappy@1: 998 | version "1.0.2" 999 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1000 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1001 | 1002 | write@1.0.3: 1003 | version "1.0.3" 1004 | resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" 1005 | integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== 1006 | dependencies: 1007 | mkdirp "^0.5.1" 1008 | 1009 | xml2js@0.4.19: 1010 | version "0.4.19" 1011 | resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" 1012 | integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== 1013 | dependencies: 1014 | sax ">=0.6.0" 1015 | xmlbuilder "~9.0.1" 1016 | 1017 | xmlbuilder@~9.0.1: 1018 | version "9.0.7" 1019 | resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" 1020 | integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= 1021 | -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const { nuxt } = require('./core/nuxt'); 4 | const { setHeadersMiddleware } = require('./middlewares/header-middleware'); 5 | const { loggerMiddleware } = require('./middlewares/logger-middleware'); 6 | const { envMiddleware } = require('./middlewares/env-middleware'); 7 | 8 | const app = express(); 9 | 10 | /** middleware */ 11 | app.use(setHeadersMiddleware); 12 | 13 | if (process.env.ENDPOINT_ENV === 'api_gw') { 14 | app.use(envMiddleware); 15 | } 16 | 17 | if (process.env.NODE_ENV !== 'development') { 18 | app.use(loggerMiddleware); 19 | } 20 | 21 | app.use(async (req, res, next) => { 22 | await nuxt.ready(); 23 | nuxt.render(req, res, next); 24 | }); 25 | 26 | module.exports.app = app; 27 | -------------------------------------------------------------------------------- /server/core/nuxt.js: -------------------------------------------------------------------------------- 1 | const { Nuxt } = require('nuxt'); 2 | const config = require('./../../nuxt.config.js'); 3 | 4 | config.dev = !(process.env.NODE_ENV === 'production'); 5 | 6 | const nuxt = new Nuxt(config); 7 | 8 | module.exports = { 9 | nuxt, 10 | config, 11 | }; 12 | -------------------------------------------------------------------------------- /server/handler.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const awsServerlessExpress = require('aws-serverless-express'); 4 | const { app } = require('./app'); 5 | 6 | const server = awsServerlessExpress.createServer(app); 7 | 8 | module.exports.render = (event, context, callback) => { 9 | console.log('[info]', 'Event', JSON.stringify(event)); 10 | awsServerlessExpress.proxy(server, event, context); 11 | }; 12 | -------------------------------------------------------------------------------- /server/local.js: -------------------------------------------------------------------------------- 1 | const { app } = require('./app'); 2 | const { nuxt, config } = require('./core/nuxt'); 3 | const { Builder } = require('nuxt'); 4 | const consola = require('consola'); 5 | 6 | const host = process.env.HOST || 'localhost'; 7 | const port = process.env.PORT || 3000; 8 | 9 | const start = async () => { 10 | if (config.dev) { 11 | const builder = new Builder(nuxt); 12 | await builder.build(); 13 | } 14 | 15 | app.listen(port, host); 16 | consola.ready({ 17 | message: `Server listening on http://${host}:${port}`, 18 | badge: true, 19 | }); 20 | }; 21 | 22 | start(); 23 | -------------------------------------------------------------------------------- /server/middlewares/cache-middleware.js: -------------------------------------------------------------------------------- 1 | /** 2 | * キャッシュを行うミドルウェアのサンプル 3 | */ 4 | 5 | const isMyPage = url => { 6 | return /^\/my/.test(url); 7 | }; 8 | 9 | const cacheMiddleware = (req, res, next) => { 10 | if (isMyPage(req.url)) { 11 | res.header('Cache-Control', 'no-store'); 12 | } else { 13 | res.header('Cache-Control', `max-age=${60}`); // 1分間 14 | } 15 | next(); 16 | }; 17 | 18 | module.exports = { 19 | cacheMiddleware, 20 | }; 21 | -------------------------------------------------------------------------------- /server/middlewares/env-middleware.js: -------------------------------------------------------------------------------- 1 | /** 2 | * API Gateway を使うときの URL に Base URL を付加するためのミドルウェア 3 | */ 4 | 5 | const BASE_URL = process.env.BASE_URL || '/'; 6 | const REGEXP_BASE_URL = new RegExp(`^${BASE_URL}`); 7 | const BASE_URL_TO_BE_ADDED = BASE_URL.replace(/\/$/, ''); 8 | const buildPath = originalPath => { 9 | if (REGEXP_BASE_URL.test(originalPath) === true) { 10 | return originalPath; 11 | } 12 | return `${BASE_URL_TO_BE_ADDED}${originalPath}`; 13 | }; 14 | 15 | const envMiddleware = (req, res, next) => { 16 | const originalUrl = req.url; 17 | const envUrl = buildPath(originalUrl); 18 | req.url = envUrl; 19 | console.log( 20 | '[info]', 21 | 'Overwrite URL', 22 | `'${originalUrl}'`, 23 | 'to', 24 | `'${envUrl}'`, 25 | ); 26 | next(); 27 | }; 28 | 29 | module.exports = { 30 | envMiddleware, 31 | }; 32 | -------------------------------------------------------------------------------- /server/middlewares/header-middleware.js: -------------------------------------------------------------------------------- 1 | /** 2 | * レスポンスヘッダーを設定するミドルウェア 3 | * XSS 対策などのヘッダーを記述 4 | */ 5 | const setHeadersMiddleware = (req, res, next) => { 6 | res.removeHeader('x-powered-by'); 7 | res.header('no-cache', 'Set-Cookie'); 8 | res.header('x-xss-protection', '1; mode=block'); 9 | res.header('x-frame-options', 'DENY'); 10 | res.header('x-content-type-options', 'nosniff'); 11 | next(); 12 | }; 13 | 14 | module.exports = { 15 | setHeadersMiddleware, 16 | }; 17 | -------------------------------------------------------------------------------- /server/middlewares/logger-middleware.js: -------------------------------------------------------------------------------- 1 | const loggerMiddleware = (req, res, next) => { 2 | console.log('[info]', 'Request URL: ', req.url); 3 | next(); 4 | }; 5 | 6 | module.exports = { 7 | loggerMiddleware, 8 | }; 9 | -------------------------------------------------------------------------------- /serverless.yml: -------------------------------------------------------------------------------- 1 | service: 2 | name: ${self:custom.NAME} 3 | 4 | frameworkVersion: ">=1.27.0" 5 | 6 | provider: 7 | name: aws 8 | runtime: nodejs12.x 9 | region: ap-northeast-1 10 | stage: ${self:custom.STAGE} 11 | 12 | custom: 13 | NAME: nuxt-on-lambda 14 | STAGE: ${file(./configs/env.js):exporter.STAGE} 15 | BASE_URL: ${file(./configs/env.js):exporter.BASE_URL} 16 | ENDPOINT_ENV: ${file(./configs/env.js):exporter.ENDPOINT_ENV} 17 | NODE_ENV: ${file(./configs/env.js):exporter.NODE_ENV} 18 | 19 | # 少しでもデプロイのパッケージファイルを少なくする 20 | package: 21 | excludeDevDependencies: true 22 | exclude: 23 | - .** 24 | - .**/* 25 | - app/** 26 | - LICENSE 27 | - README.md 28 | - package.json 29 | - yarn.lock 30 | # Node.js 上で使われないモジュール 31 | # 重いものを優先的に除外 32 | - node_modules/babel**/** 33 | - node_modules/caniuse-db/** 34 | - node_modules/prettier/** 35 | - node_modules/yargs/** 36 | - node_modules/xxhashjs/** 37 | - node_modules/jschardet/** 38 | - node_modules/**/*.md 39 | - node_modules/**/bin/** 40 | include: 41 | - server/** 42 | - configs/** 43 | - nuxt.config.js 44 | - .nuxt/** 45 | - node_modules/autoprefixer/** 46 | - node_modules/babel-runtime/** 47 | - node_modules/babel-extract-comments/** 48 | 49 | 50 | functions: 51 | render: 52 | handler: server/handler.render 53 | timeout: 30 54 | memorySize: 128 55 | environment: 56 | BASE_URL: ${self:custom.BASE_URL} 57 | ENDPOINT_ENV: ${self:custom.ENDPOINT_ENV} 58 | NODE_ENV: ${self:custom.NODE_ENV} 59 | events: 60 | - http: 61 | path: '/' 62 | method: get 63 | - http: 64 | path: '{proxy+}' 65 | method: get 66 | 67 | --------------------------------------------------------------------------------