├── .eslintrc.yml ├── .gitignore ├── README.md ├── chart.js ├── gateway-1.0.0.tgz ├── gateway ├── Chart.yaml ├── templates │ ├── deployment-gateway.yaml │ ├── hpa-gateway.yaml │ ├── secret-my.yaml │ └── service-gateway.yaml └── values.yaml ├── k8s ├── deployment-gateway.yaml ├── secret.yaml └── service-gateway.yaml └── src └── gateway ├── Dockerfile ├── index.js ├── package-lock.json ├── package.json └── server.js /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | extends: airbnb-base 3 | env: 4 | node: true 5 | mocha: true 6 | es6: true 7 | parserOptions: 8 | sourceType: strict 9 | rules: 10 | no-console: 0 11 | new-cap: 0 12 | generator-star-spacing: 13 | - 2 14 | - before: true 15 | after: true 16 | no-shadow: 0 17 | require-yield: 0 18 | no-param-reassign: 0 19 | comma-dangle: 20 | - error 21 | - never 22 | no-underscore-dangle: 0 23 | import/no-extraneous-dependencies: 24 | - 2 25 | - devDependencies: true 26 | import/order: 27 | - error 28 | func-names: 0 29 | no-unused-expressions: 0 30 | prefer-arrow-callback: 1 31 | no-use-before-define: 32 | - 2 33 | - functions: false 34 | space-before-function-paren: 35 | - 2 36 | - always 37 | max-len: 38 | - 2 39 | - 120 40 | - 2 41 | semi: 42 | - 2 43 | - never 44 | strict: 45 | - 2 46 | - global 47 | arrow-parens: 48 | - 2 49 | - always 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # example-kubernetes-nodejs 2 | 3 | Introduction to `Kubernetes` (k8s) with `Node.js`. 4 | 5 | ## Requirements 6 | 7 | - Kubernetes (or minikube) 8 | - kubectl 9 | - Docker 10 | 11 | ## Helpers 12 | 13 | - Re-using local Docker daemon with minikube: `eval $(minikube docker-env)` (run it once before Docker build) 14 | - On OSX: To base64: `pbpaste | base64 | pbcopy` and From base64: `pbcopy | base64 --decode` 15 | - `minikube start` and `minikube stop` 16 | 17 | ## Tasks 18 | 19 | ### 1. Build Docker image 20 | 21 | Re-using local Docker daemon with minikube: 22 | 23 | ```sh 24 | eval $(minikube docker-env) 25 | ``` 26 | 27 | Building Docker image: 28 | 29 | ```sh 30 | cd src/gateway 31 | docker build -t my-co/gateway:v1 . 32 | ``` 33 | 34 | ### 2. Create Secret, Deployment and Service in Kubernetes 35 | 36 | ```sh 37 | kubectl create -f k8s 38 | kubectl get deployment 39 | kubectl get deployment -o yaml 40 | kubectl edit deployment 41 | kubectl get secret 42 | kubectl get secret -o yaml 43 | kubectl get service 44 | kubectl get service -o yaml 45 | ``` 46 | 47 | ### 3. Get running pods 48 | 49 | ```sh 50 | kubectl get pod 51 | kubectl describe pod 52 | ``` 53 | 54 | Edit replica number in gateway Deployment and get pods again. 55 | WARNING: Always edit `yaml` files in Kubernetes via `kubectl`, it's not synchronized with your local `k8s` folder. 56 | 57 | ### 4. Kill one pod 58 | 59 | ```sh 60 | kubectl get pod 61 | kubectl delete pod 62 | kubectl get pod 63 | ``` 64 | 65 | ### 5. Test networking 66 | 67 | Go to inside a running pod: 68 | 69 | ```sh 70 | kubectl get pod 71 | kubectl exec -it -- sh 72 | nslookup kubernetes gateway 73 | curl :3001 74 | curl :3001 75 | env | grep GATEWAY 76 | ``` 77 | 78 | From minikibe: 79 | 80 | ``` 81 | minikube service gateway 82 | ``` 83 | 84 | ### 6. Set Horizontal Pod Autoscaler (HPA) 85 | 86 | Do you have a running Heapster (collects metrics for autoscaler)? 87 | 88 | ```sh 89 | kubectl get pod -n kube-system 90 | ``` 91 | 92 | If not, enable it: 93 | 94 | ```sh 95 | $ minikube addons list 96 | - addon-manager: enabled 97 | - dashboard: enabled 98 | - kube-dns: enabled 99 | - heapster: disabled 100 | - registry-creds: disabled 101 | 102 | # minikube must be running for these commands to take effect 103 | $ minikube addons enable heapster 104 | heapster was successfully enabled 105 | 106 | # this may take some time 107 | $ kubectl get pod -n kube-system 108 | NAME READY STATUS RESTARTS AGE 109 | heapster-2b7mt 1/1 Running 0 4m 110 | ``` 111 | 112 | ```sh 113 | kubectl autoscale deployment gateway --cpu-percent=50 --min=1 --max=10 114 | kubectl get hpa 115 | kubectl get hpa gateway -o yaml 116 | ab -n 10000 -c 100 117 | ``` 118 | 119 | HPA runs every 2 minutes by default. 120 | 121 | ### 7. Templating 122 | 123 | Checkout [Helm](https://github.com/kubernetes/helm) and [anchor](https://github.com/RisingStack/anchor). 124 | 125 | Install helm, then: 126 | 127 | ```sh 128 | $ helm init 129 | Creating /Users/foo/.helm 130 | Creating /Users/foo/.helm/repository 131 | Creating /Users/foo/.helm/repository/cache 132 | Creating /Users/foo/.helm/repository/local 133 | Creating /Users/foo/.helm/plugins 134 | Creating /Users/foo/.helm/starters 135 | Creating /Users/foo/.helm/cache/archive 136 | Creating /Users/foo/.helm/repository/repositories.yaml 137 | $HELM_HOME has been configured at /Users/foo/.helm. 138 | 139 | # this will take a while 140 | $ kubectl get pod -n kube-system 141 | NAME READY STATUS RESTARTS AGE 142 | tiller-deploy-1936853538-3brdf 1/1 Running 0 7m 143 | ``` 144 | 145 | Backup your infrastructure: 146 | 147 | ```sh 148 | node chart.js 149 | ``` 150 | 151 | Your templates will be saved in `gateway/templates/` 152 | 153 | ```sh 154 | helm package gateway 155 | ``` 156 | 157 | On a fresh cluster run: 158 | 159 | ```sh 160 | helm install gateway 161 | ``` 162 | 163 | and your infrastructure should be restored. 164 | -------------------------------------------------------------------------------- /chart.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const anchor = require('@risingstack/anchor') 4 | 5 | anchor.snapshot({ 6 | overwrite: true, 7 | outputPath: './gateway', 8 | name: 'gateway', 9 | description: 'Backup of gateway service', 10 | version: '1.0.0', 11 | namespace: 'default', 12 | resources: [ 13 | 'deployment/gateway', 14 | 'secret/my', 15 | 'service/gateway', 16 | 'hpa/gateway' 17 | ] 18 | }) 19 | .then(() => console.log('Snapshot finished')) 20 | .catch((err) => console.error('Snapshot error', err)) 21 | -------------------------------------------------------------------------------- /gateway-1.0.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RisingStack/example-kubernetes-nodejs/9ce3a8eecda442bae93d4b8932b0b753affcdeee/gateway-1.0.0.tgz -------------------------------------------------------------------------------- /gateway/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | description: Backup of gateway service 3 | name: gateway 4 | version: 1.0.0 5 | -------------------------------------------------------------------------------- /gateway/templates/deployment-gateway.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | deployment.kubernetes.io/revision: '5' 6 | generation: 1 7 | labels: 8 | app: gateway 9 | name: gateway 10 | spec: 11 | progressDeadlineSeconds: 600 12 | replicas: {{ .Values.deploymentGateway.replicas | default 2 }} 13 | revisionHistoryLimit: 2 14 | selector: 15 | matchLabels: 16 | app: gateway 17 | strategy: 18 | rollingUpdate: 19 | maxSurge: 25% 20 | maxUnavailable: 25% 21 | type: RollingUpdate 22 | template: 23 | metadata: 24 | labels: 25 | app: gateway 26 | spec: 27 | containers: 28 | - env: 29 | - name: MY_SECRET 30 | valueFrom: 31 | secretKeyRef: 32 | key: secret 33 | name: my 34 | image: '"{{ .Values.deploymentGateway.image }}:{{ .Values.deploymentGateway.imageTag }}"' 35 | imagePullPolicy: IfNotPresent 36 | livenessProbe: 37 | failureThreshold: 3 38 | httpGet: 39 | path: /healthz 40 | port: 3001 41 | scheme: HTTP 42 | initialDelaySeconds: 3 43 | periodSeconds: 3 44 | successThreshold: 1 45 | timeoutSeconds: 1 46 | name: gateway 47 | ports: 48 | - containerPort: 3001 49 | protocol: TCP 50 | readinessProbe: 51 | failureThreshold: 3 52 | httpGet: 53 | path: /healthz 54 | port: 3001 55 | scheme: HTTP 56 | initialDelaySeconds: 3 57 | periodSeconds: 3 58 | successThreshold: 1 59 | timeoutSeconds: 1 60 | resources: 61 | limits: 62 | cpu: {{ .Values.deploymentGateway.resourcesLimitsCPU | default "55m" }} 63 | memory: {{ .Values.deploymentGateway.resourcesLimitsMemory | default "1536Mi" }} 64 | requests: 65 | cpu: {{ .Values.deploymentGateway.resourcesRequestsCPU | default "50m" }} 66 | memory: {{ .Values.deploymentGateway.resourcesRequestsMemory | default "100Mi" }} 67 | terminationMessagePath: /dev/termination-log 68 | terminationMessagePolicy: File 69 | dnsPolicy: ClusterFirst 70 | restartPolicy: Always 71 | schedulerName: default-scheduler 72 | securityContext: {} 73 | terminationGracePeriodSeconds: 30 74 | -------------------------------------------------------------------------------- /gateway/templates/hpa-gateway.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: autoscaling/v1 2 | kind: HorizontalPodAutoscaler 3 | metadata: 4 | creationTimestamp: null 5 | name: gateway 6 | selfLink: /apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/gateway 7 | spec: 8 | maxReplicas: 10 9 | minReplicas: 1 10 | scaleTargetRef: 11 | apiVersion: extensions/v1beta1 12 | kind: Deployment 13 | name: gateway 14 | targetCPUUtilizationPercentage: 50 15 | status: 16 | currentReplicas: 0 17 | desiredReplicas: 0 18 | -------------------------------------------------------------------------------- /gateway/templates/secret-my.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | data: 3 | secret: {{ .Values.secretMy.secret | b64enc }} 4 | kind: Secret 5 | metadata: 6 | name: my 7 | type: Opaque 8 | -------------------------------------------------------------------------------- /gateway/templates/service-gateway.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: gateway 5 | spec: 6 | externalTrafficPolicy: Cluster 7 | ports: 8 | - port: 80 9 | protocol: TCP 10 | targetPort: 3001 11 | selector: 12 | app: gateway 13 | sessionAffinity: None 14 | type: {{ .Values.serviceGateway.type | default "NodePort" }} 15 | -------------------------------------------------------------------------------- /gateway/values.yaml: -------------------------------------------------------------------------------- 1 | deploymentGateway: 2 | image: my-co/gateway 3 | imageTag: v1 4 | resourcesLimitsCPU: 55m 5 | resourcesLimitsMemory: 1536Mi 6 | resourcesRequestsCPU: 50m 7 | resourcesRequestsMemory: 100Mi 8 | replicas: 2 9 | secretMy: 10 | secret: | 11 | training 12 | serviceGateway: 13 | type: NodePort 14 | hpaGateway: {} 15 | -------------------------------------------------------------------------------- /k8s/deployment-gateway.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: gateway 5 | spec: 6 | replicas: 2 7 | template: 8 | metadata: 9 | labels: 10 | app: gateway 11 | track: black 12 | spec: 13 | containers: 14 | - name: gateway 15 | image: my-co/gateway:v1 16 | ports: 17 | - containerPort: 3001 18 | resources: 19 | requests: 20 | memory: 100Mi 21 | cpu: 50m 22 | limits: 23 | memory: 1536Mi 24 | cpu: 55m 25 | env: 26 | - name: MY_SECRET 27 | valueFrom: 28 | secretKeyRef: 29 | name: my 30 | key: secret 31 | livenessProbe: 32 | httpGet: 33 | path: /healthz 34 | port: 3001 35 | initialDelaySeconds: 3 36 | failureThreshold: 3 37 | periodSeconds: 3 38 | readinessProbe: 39 | httpGet: 40 | path: /healthz 41 | port: 3001 42 | initialDelaySeconds: 1 43 | failureThreshold: 3 44 | periodSeconds: 1 45 | -------------------------------------------------------------------------------- /k8s/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: my 5 | type: Opaque 6 | data: 7 | secret: dHJhaW5pbmcK 8 | -------------------------------------------------------------------------------- /k8s/service-gateway.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: gateway 5 | spec: 6 | type: NodePort 7 | selector: 8 | app: gateway 9 | ports: 10 | - protocol: TCP 11 | port: 80 12 | targetPort: 3001 13 | -------------------------------------------------------------------------------- /src/gateway/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM risingstack/alpine:3.4-v6.9.4-4.2.0 2 | 3 | ENV PORT 3001 4 | 5 | EXPOSE 3001 6 | 7 | COPY package.json package.json 8 | RUN npm install 9 | 10 | # Add your source files 11 | COPY . . 12 | 13 | CMD ["node", "."] 14 | -------------------------------------------------------------------------------- /src/gateway/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = require('./server') 4 | -------------------------------------------------------------------------------- /src/gateway/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gateway", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "accepts": { 7 | "version": "1.3.3", 8 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", 9 | "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=" 10 | }, 11 | "acorn": { 12 | "version": "5.0.3", 13 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", 14 | "integrity": "sha1-xGDfCEkUY/AozLguqzcwvwEIez0=", 15 | "dev": true 16 | }, 17 | "acorn-jsx": { 18 | "version": "3.0.1", 19 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", 20 | "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", 21 | "dev": true, 22 | "dependencies": { 23 | "acorn": { 24 | "version": "3.3.0", 25 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 26 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", 27 | "dev": true 28 | } 29 | } 30 | }, 31 | "ajv": { 32 | "version": "4.11.8", 33 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", 34 | "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", 35 | "dev": true 36 | }, 37 | "ajv-keywords": { 38 | "version": "1.5.1", 39 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", 40 | "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", 41 | "dev": true 42 | }, 43 | "ansi-escapes": { 44 | "version": "1.4.0", 45 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", 46 | "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", 47 | "dev": true 48 | }, 49 | "ansi-regex": { 50 | "version": "2.1.1", 51 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 52 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 53 | "dev": true 54 | }, 55 | "ansi-styles": { 56 | "version": "2.2.1", 57 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 58 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", 59 | "dev": true 60 | }, 61 | "argparse": { 62 | "version": "1.0.9", 63 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", 64 | "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", 65 | "dev": true 66 | }, 67 | "array-flatten": { 68 | "version": "1.1.1", 69 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 70 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 71 | }, 72 | "array-union": { 73 | "version": "1.0.2", 74 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", 75 | "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", 76 | "dev": true 77 | }, 78 | "array-uniq": { 79 | "version": "1.0.3", 80 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", 81 | "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", 82 | "dev": true 83 | }, 84 | "arrify": { 85 | "version": "1.0.1", 86 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 87 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 88 | "dev": true 89 | }, 90 | "babel-code-frame": { 91 | "version": "6.22.0", 92 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", 93 | "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", 94 | "dev": true 95 | }, 96 | "balanced-match": { 97 | "version": "1.0.0", 98 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 99 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 100 | "dev": true 101 | }, 102 | "brace-expansion": { 103 | "version": "1.1.8", 104 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", 105 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", 106 | "dev": true 107 | }, 108 | "builtin-modules": { 109 | "version": "1.1.1", 110 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 111 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", 112 | "dev": true 113 | }, 114 | "caller-path": { 115 | "version": "0.1.0", 116 | "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", 117 | "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", 118 | "dev": true 119 | }, 120 | "callsites": { 121 | "version": "0.2.0", 122 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", 123 | "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", 124 | "dev": true 125 | }, 126 | "chalk": { 127 | "version": "1.1.3", 128 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 129 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 130 | "dev": true 131 | }, 132 | "circular-json": { 133 | "version": "0.3.1", 134 | "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", 135 | "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=", 136 | "dev": true 137 | }, 138 | "cli-cursor": { 139 | "version": "1.0.2", 140 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", 141 | "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", 142 | "dev": true 143 | }, 144 | "cli-width": { 145 | "version": "2.1.0", 146 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", 147 | "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", 148 | "dev": true 149 | }, 150 | "co": { 151 | "version": "4.6.0", 152 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 153 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", 154 | "dev": true 155 | }, 156 | "code-point-at": { 157 | "version": "1.1.0", 158 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 159 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", 160 | "dev": true 161 | }, 162 | "concat-map": { 163 | "version": "0.0.1", 164 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 165 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 166 | "dev": true 167 | }, 168 | "concat-stream": { 169 | "version": "1.6.0", 170 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", 171 | "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", 172 | "dev": true 173 | }, 174 | "contains-path": { 175 | "version": "0.1.0", 176 | "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", 177 | "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", 178 | "dev": true 179 | }, 180 | "content-disposition": { 181 | "version": "0.5.2", 182 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 183 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 184 | }, 185 | "content-type": { 186 | "version": "1.0.2", 187 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", 188 | "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=" 189 | }, 190 | "cookie": { 191 | "version": "0.3.1", 192 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 193 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 194 | }, 195 | "cookie-signature": { 196 | "version": "1.0.6", 197 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 198 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 199 | }, 200 | "core-util-is": { 201 | "version": "1.0.2", 202 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 203 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 204 | "dev": true 205 | }, 206 | "d": { 207 | "version": "1.0.0", 208 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", 209 | "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", 210 | "dev": true 211 | }, 212 | "debug": { 213 | "version": "2.6.8", 214 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", 215 | "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", 216 | "dev": true 217 | }, 218 | "deep-is": { 219 | "version": "0.1.3", 220 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 221 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 222 | "dev": true 223 | }, 224 | "del": { 225 | "version": "2.2.2", 226 | "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", 227 | "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", 228 | "dev": true 229 | }, 230 | "depd": { 231 | "version": "1.1.0", 232 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", 233 | "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=" 234 | }, 235 | "destroy": { 236 | "version": "1.0.4", 237 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 238 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 239 | }, 240 | "doctrine": { 241 | "version": "2.0.0", 242 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", 243 | "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", 244 | "dev": true 245 | }, 246 | "ee-first": { 247 | "version": "1.1.1", 248 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 249 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 250 | }, 251 | "encodeurl": { 252 | "version": "1.0.1", 253 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", 254 | "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" 255 | }, 256 | "es5-ext": { 257 | "version": "0.10.23", 258 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.23.tgz", 259 | "integrity": "sha1-dXi1G+l0IHpUh4IbVlOMIk5Oezg=", 260 | "dev": true 261 | }, 262 | "es6-iterator": { 263 | "version": "2.0.1", 264 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", 265 | "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", 266 | "dev": true 267 | }, 268 | "es6-map": { 269 | "version": "0.1.5", 270 | "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", 271 | "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", 272 | "dev": true 273 | }, 274 | "es6-set": { 275 | "version": "0.1.5", 276 | "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", 277 | "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", 278 | "dev": true 279 | }, 280 | "es6-symbol": { 281 | "version": "3.1.1", 282 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", 283 | "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", 284 | "dev": true 285 | }, 286 | "es6-weak-map": { 287 | "version": "2.0.2", 288 | "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", 289 | "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", 290 | "dev": true 291 | }, 292 | "escape-html": { 293 | "version": "1.0.3", 294 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 295 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 296 | }, 297 | "escape-string-regexp": { 298 | "version": "1.0.5", 299 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 300 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 301 | "dev": true 302 | }, 303 | "escope": { 304 | "version": "3.6.0", 305 | "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", 306 | "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", 307 | "dev": true 308 | }, 309 | "eslint": { 310 | "version": "3.19.0", 311 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", 312 | "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", 313 | "dev": true 314 | }, 315 | "eslint-config-airbnb-base": { 316 | "version": "11.2.0", 317 | "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.2.0.tgz", 318 | "integrity": "sha1-GancRIGib3CQRUXsBAEWh2AY+FM=", 319 | "dev": true 320 | }, 321 | "eslint-import-resolver-node": { 322 | "version": "0.2.3", 323 | "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", 324 | "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", 325 | "dev": true 326 | }, 327 | "eslint-module-utils": { 328 | "version": "2.1.1", 329 | "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", 330 | "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", 331 | "dev": true 332 | }, 333 | "eslint-plugin-import": { 334 | "version": "2.2.0", 335 | "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz", 336 | "integrity": "sha1-crowb60wXWfEgWNIpGmaQimsi04=", 337 | "dev": true, 338 | "dependencies": { 339 | "doctrine": { 340 | "version": "1.5.0", 341 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", 342 | "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", 343 | "dev": true 344 | } 345 | } 346 | }, 347 | "eslint-plugin-promise": { 348 | "version": "3.5.0", 349 | "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz", 350 | "integrity": "sha1-ePu2/+BHIBYnVp6FpsU3OvKmj8o=", 351 | "dev": true 352 | }, 353 | "espree": { 354 | "version": "3.4.3", 355 | "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", 356 | "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=", 357 | "dev": true 358 | }, 359 | "esprima": { 360 | "version": "3.1.3", 361 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", 362 | "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", 363 | "dev": true 364 | }, 365 | "esquery": { 366 | "version": "1.0.0", 367 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", 368 | "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", 369 | "dev": true 370 | }, 371 | "esrecurse": { 372 | "version": "4.2.0", 373 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", 374 | "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", 375 | "dev": true 376 | }, 377 | "estraverse": { 378 | "version": "4.2.0", 379 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", 380 | "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", 381 | "dev": true 382 | }, 383 | "esutils": { 384 | "version": "2.0.2", 385 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 386 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 387 | "dev": true 388 | }, 389 | "etag": { 390 | "version": "1.8.0", 391 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", 392 | "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE=" 393 | }, 394 | "event-emitter": { 395 | "version": "0.3.5", 396 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", 397 | "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", 398 | "dev": true 399 | }, 400 | "exit-hook": { 401 | "version": "1.1.1", 402 | "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", 403 | "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", 404 | "dev": true 405 | }, 406 | "express": { 407 | "version": "4.15.3", 408 | "resolved": "https://registry.npmjs.org/express/-/express-4.15.3.tgz", 409 | "integrity": "sha1-urZdDwOqgMNYQIly/HAPkWlEtmI=", 410 | "dependencies": { 411 | "debug": { 412 | "version": "2.6.7", 413 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", 414 | "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=" 415 | } 416 | } 417 | }, 418 | "fast-levenshtein": { 419 | "version": "2.0.6", 420 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 421 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 422 | "dev": true 423 | }, 424 | "figures": { 425 | "version": "1.7.0", 426 | "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", 427 | "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", 428 | "dev": true 429 | }, 430 | "file-entry-cache": { 431 | "version": "2.0.0", 432 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", 433 | "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", 434 | "dev": true 435 | }, 436 | "finalhandler": { 437 | "version": "1.0.3", 438 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz", 439 | "integrity": "sha1-70fneVDpmXgOhgIqVg4yF+DQzIk=", 440 | "dependencies": { 441 | "debug": { 442 | "version": "2.6.7", 443 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", 444 | "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=" 445 | } 446 | } 447 | }, 448 | "find-up": { 449 | "version": "1.1.2", 450 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", 451 | "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", 452 | "dev": true 453 | }, 454 | "flat-cache": { 455 | "version": "1.2.2", 456 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", 457 | "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", 458 | "dev": true 459 | }, 460 | "forwarded": { 461 | "version": "0.1.0", 462 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", 463 | "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=" 464 | }, 465 | "fresh": { 466 | "version": "0.5.0", 467 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", 468 | "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=" 469 | }, 470 | "fs.realpath": { 471 | "version": "1.0.0", 472 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 473 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 474 | "dev": true 475 | }, 476 | "function-bind": { 477 | "version": "1.1.0", 478 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", 479 | "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", 480 | "dev": true 481 | }, 482 | "generate-function": { 483 | "version": "2.0.0", 484 | "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", 485 | "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", 486 | "dev": true 487 | }, 488 | "generate-object-property": { 489 | "version": "1.2.0", 490 | "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", 491 | "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", 492 | "dev": true 493 | }, 494 | "glob": { 495 | "version": "7.1.2", 496 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 497 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 498 | "dev": true 499 | }, 500 | "globals": { 501 | "version": "9.18.0", 502 | "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", 503 | "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", 504 | "dev": true 505 | }, 506 | "globby": { 507 | "version": "5.0.0", 508 | "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", 509 | "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", 510 | "dev": true 511 | }, 512 | "graceful-fs": { 513 | "version": "4.1.11", 514 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 515 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", 516 | "dev": true 517 | }, 518 | "has": { 519 | "version": "1.0.1", 520 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", 521 | "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", 522 | "dev": true 523 | }, 524 | "has-ansi": { 525 | "version": "2.0.0", 526 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 527 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 528 | "dev": true 529 | }, 530 | "http-errors": { 531 | "version": "1.6.1", 532 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", 533 | "integrity": "sha1-X4uO2YrKVFZWv1cplzh/kEpyIlc=" 534 | }, 535 | "ignore": { 536 | "version": "3.3.3", 537 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", 538 | "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", 539 | "dev": true 540 | }, 541 | "imurmurhash": { 542 | "version": "0.1.4", 543 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 544 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 545 | "dev": true 546 | }, 547 | "inflight": { 548 | "version": "1.0.6", 549 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 550 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 551 | "dev": true 552 | }, 553 | "inherits": { 554 | "version": "2.0.3", 555 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 556 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 557 | }, 558 | "inquirer": { 559 | "version": "0.12.0", 560 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", 561 | "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", 562 | "dev": true 563 | }, 564 | "interpret": { 565 | "version": "1.0.3", 566 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", 567 | "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", 568 | "dev": true 569 | }, 570 | "ipaddr.js": { 571 | "version": "1.3.0", 572 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.3.0.tgz", 573 | "integrity": "sha1-HgOlL9rYOou7KyXL9JmLTP/NPew=" 574 | }, 575 | "is-fullwidth-code-point": { 576 | "version": "1.0.0", 577 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 578 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 579 | "dev": true 580 | }, 581 | "is-my-json-valid": { 582 | "version": "2.16.0", 583 | "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz", 584 | "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=", 585 | "dev": true 586 | }, 587 | "is-path-cwd": { 588 | "version": "1.0.0", 589 | "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", 590 | "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", 591 | "dev": true 592 | }, 593 | "is-path-in-cwd": { 594 | "version": "1.0.0", 595 | "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", 596 | "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", 597 | "dev": true 598 | }, 599 | "is-path-inside": { 600 | "version": "1.0.0", 601 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", 602 | "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", 603 | "dev": true 604 | }, 605 | "is-property": { 606 | "version": "1.0.2", 607 | "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", 608 | "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", 609 | "dev": true 610 | }, 611 | "is-resolvable": { 612 | "version": "1.0.0", 613 | "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", 614 | "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", 615 | "dev": true 616 | }, 617 | "isarray": { 618 | "version": "1.0.0", 619 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 620 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 621 | "dev": true 622 | }, 623 | "js-tokens": { 624 | "version": "3.0.1", 625 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", 626 | "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", 627 | "dev": true 628 | }, 629 | "js-yaml": { 630 | "version": "3.8.4", 631 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz", 632 | "integrity": "sha1-UgtFZPhlc7qWZir4Woyvp7S1pvY=", 633 | "dev": true 634 | }, 635 | "json-stable-stringify": { 636 | "version": "1.0.1", 637 | "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", 638 | "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", 639 | "dev": true 640 | }, 641 | "jsonify": { 642 | "version": "0.0.0", 643 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", 644 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", 645 | "dev": true 646 | }, 647 | "jsonpointer": { 648 | "version": "4.0.1", 649 | "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", 650 | "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", 651 | "dev": true 652 | }, 653 | "levn": { 654 | "version": "0.3.0", 655 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 656 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 657 | "dev": true 658 | }, 659 | "lodash": { 660 | "version": "4.17.4", 661 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", 662 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", 663 | "dev": true 664 | }, 665 | "lodash.cond": { 666 | "version": "4.5.2", 667 | "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", 668 | "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", 669 | "dev": true 670 | }, 671 | "media-typer": { 672 | "version": "0.3.0", 673 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 674 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 675 | }, 676 | "merge-descriptors": { 677 | "version": "1.0.1", 678 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 679 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 680 | }, 681 | "methods": { 682 | "version": "1.1.2", 683 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 684 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 685 | }, 686 | "mime": { 687 | "version": "1.3.4", 688 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", 689 | "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" 690 | }, 691 | "mime-db": { 692 | "version": "1.27.0", 693 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", 694 | "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=" 695 | }, 696 | "mime-types": { 697 | "version": "2.1.15", 698 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", 699 | "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=" 700 | }, 701 | "minimatch": { 702 | "version": "3.0.4", 703 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 704 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 705 | "dev": true 706 | }, 707 | "minimist": { 708 | "version": "0.0.8", 709 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 710 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 711 | "dev": true 712 | }, 713 | "mkdirp": { 714 | "version": "0.5.1", 715 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 716 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 717 | "dev": true 718 | }, 719 | "ms": { 720 | "version": "2.0.0", 721 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 722 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 723 | }, 724 | "mute-stream": { 725 | "version": "0.0.5", 726 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", 727 | "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", 728 | "dev": true 729 | }, 730 | "natural-compare": { 731 | "version": "1.4.0", 732 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 733 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 734 | "dev": true 735 | }, 736 | "negotiator": { 737 | "version": "0.6.1", 738 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 739 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 740 | }, 741 | "number-is-nan": { 742 | "version": "1.0.1", 743 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 744 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", 745 | "dev": true 746 | }, 747 | "object-assign": { 748 | "version": "4.1.1", 749 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 750 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 751 | "dev": true 752 | }, 753 | "on-finished": { 754 | "version": "2.3.0", 755 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 756 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=" 757 | }, 758 | "once": { 759 | "version": "1.4.0", 760 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 761 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 762 | "dev": true 763 | }, 764 | "onetime": { 765 | "version": "1.1.0", 766 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", 767 | "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", 768 | "dev": true 769 | }, 770 | "optionator": { 771 | "version": "0.8.2", 772 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 773 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 774 | "dev": true 775 | }, 776 | "os-homedir": { 777 | "version": "1.0.2", 778 | "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", 779 | "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", 780 | "dev": true 781 | }, 782 | "parseurl": { 783 | "version": "1.3.1", 784 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", 785 | "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=" 786 | }, 787 | "path-exists": { 788 | "version": "2.1.0", 789 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", 790 | "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", 791 | "dev": true 792 | }, 793 | "path-is-absolute": { 794 | "version": "1.0.1", 795 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 796 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 797 | "dev": true 798 | }, 799 | "path-is-inside": { 800 | "version": "1.0.2", 801 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 802 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", 803 | "dev": true 804 | }, 805 | "path-parse": { 806 | "version": "1.0.5", 807 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", 808 | "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", 809 | "dev": true 810 | }, 811 | "path-to-regexp": { 812 | "version": "0.1.7", 813 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 814 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 815 | }, 816 | "pify": { 817 | "version": "2.3.0", 818 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 819 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 820 | "dev": true 821 | }, 822 | "pinkie": { 823 | "version": "2.0.4", 824 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 825 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", 826 | "dev": true 827 | }, 828 | "pinkie-promise": { 829 | "version": "2.0.1", 830 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 831 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 832 | "dev": true 833 | }, 834 | "pkg-dir": { 835 | "version": "1.0.0", 836 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", 837 | "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", 838 | "dev": true 839 | }, 840 | "pkg-up": { 841 | "version": "1.0.0", 842 | "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", 843 | "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", 844 | "dev": true 845 | }, 846 | "pluralize": { 847 | "version": "1.2.1", 848 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", 849 | "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", 850 | "dev": true 851 | }, 852 | "prelude-ls": { 853 | "version": "1.1.2", 854 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 855 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 856 | "dev": true 857 | }, 858 | "process-nextick-args": { 859 | "version": "1.0.7", 860 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 861 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", 862 | "dev": true 863 | }, 864 | "progress": { 865 | "version": "1.1.8", 866 | "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", 867 | "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", 868 | "dev": true 869 | }, 870 | "proxy-addr": { 871 | "version": "1.1.4", 872 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.4.tgz", 873 | "integrity": "sha1-J+VF9pYKRKYn2bREZ+NcG2tM4vM=" 874 | }, 875 | "qs": { 876 | "version": "6.4.0", 877 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", 878 | "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" 879 | }, 880 | "range-parser": { 881 | "version": "1.2.0", 882 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 883 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 884 | }, 885 | "readable-stream": { 886 | "version": "2.3.2", 887 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.2.tgz", 888 | "integrity": "sha1-WgTfBeT1f+Pw3Gj90R3FyXx+b00=", 889 | "dev": true 890 | }, 891 | "readline2": { 892 | "version": "1.0.1", 893 | "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", 894 | "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", 895 | "dev": true 896 | }, 897 | "rechoir": { 898 | "version": "0.6.2", 899 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", 900 | "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", 901 | "dev": true 902 | }, 903 | "require-uncached": { 904 | "version": "1.0.3", 905 | "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", 906 | "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", 907 | "dev": true 908 | }, 909 | "resolve": { 910 | "version": "1.3.3", 911 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", 912 | "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", 913 | "dev": true 914 | }, 915 | "resolve-from": { 916 | "version": "1.0.1", 917 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", 918 | "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", 919 | "dev": true 920 | }, 921 | "restore-cursor": { 922 | "version": "1.0.1", 923 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", 924 | "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", 925 | "dev": true 926 | }, 927 | "rimraf": { 928 | "version": "2.6.1", 929 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", 930 | "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", 931 | "dev": true 932 | }, 933 | "run-async": { 934 | "version": "0.1.0", 935 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", 936 | "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", 937 | "dev": true 938 | }, 939 | "rx-lite": { 940 | "version": "3.1.2", 941 | "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", 942 | "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", 943 | "dev": true 944 | }, 945 | "safe-buffer": { 946 | "version": "5.1.1", 947 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 948 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", 949 | "dev": true 950 | }, 951 | "send": { 952 | "version": "0.15.3", 953 | "resolved": "https://registry.npmjs.org/send/-/send-0.15.3.tgz", 954 | "integrity": "sha1-UBP5+ZAj31DRvZiSwZ4979HVMwk=", 955 | "dependencies": { 956 | "debug": { 957 | "version": "2.6.7", 958 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", 959 | "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=" 960 | } 961 | } 962 | }, 963 | "serve-static": { 964 | "version": "1.12.3", 965 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.3.tgz", 966 | "integrity": "sha1-n0uhni8wMMVH+K+ZEHg47DjVseI=" 967 | }, 968 | "setprototypeof": { 969 | "version": "1.0.3", 970 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 971 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 972 | }, 973 | "shelljs": { 974 | "version": "0.7.8", 975 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", 976 | "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", 977 | "dev": true 978 | }, 979 | "slice-ansi": { 980 | "version": "0.0.4", 981 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", 982 | "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", 983 | "dev": true 984 | }, 985 | "sprintf-js": { 986 | "version": "1.0.3", 987 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 988 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 989 | "dev": true 990 | }, 991 | "statuses": { 992 | "version": "1.3.1", 993 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", 994 | "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" 995 | }, 996 | "string_decoder": { 997 | "version": "1.0.3", 998 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 999 | "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 1000 | "dev": true 1001 | }, 1002 | "string-width": { 1003 | "version": "1.0.2", 1004 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 1005 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 1006 | "dev": true 1007 | }, 1008 | "strip-ansi": { 1009 | "version": "3.0.1", 1010 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1011 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1012 | "dev": true 1013 | }, 1014 | "strip-bom": { 1015 | "version": "3.0.0", 1016 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 1017 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", 1018 | "dev": true 1019 | }, 1020 | "strip-json-comments": { 1021 | "version": "2.0.1", 1022 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1023 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1024 | "dev": true 1025 | }, 1026 | "supports-color": { 1027 | "version": "2.0.0", 1028 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 1029 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", 1030 | "dev": true 1031 | }, 1032 | "table": { 1033 | "version": "3.8.3", 1034 | "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", 1035 | "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", 1036 | "dev": true, 1037 | "dependencies": { 1038 | "is-fullwidth-code-point": { 1039 | "version": "2.0.0", 1040 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 1041 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 1042 | "dev": true 1043 | }, 1044 | "string-width": { 1045 | "version": "2.0.0", 1046 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.0.0.tgz", 1047 | "integrity": "sha1-Y1xUNsxypuDDh87KJ41OLuxSaH4=", 1048 | "dev": true 1049 | } 1050 | } 1051 | }, 1052 | "text-table": { 1053 | "version": "0.2.0", 1054 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1055 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1056 | "dev": true 1057 | }, 1058 | "through": { 1059 | "version": "2.3.8", 1060 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1061 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 1062 | "dev": true 1063 | }, 1064 | "tryit": { 1065 | "version": "1.0.3", 1066 | "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", 1067 | "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", 1068 | "dev": true 1069 | }, 1070 | "type-check": { 1071 | "version": "0.3.2", 1072 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1073 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1074 | "dev": true 1075 | }, 1076 | "type-is": { 1077 | "version": "1.6.15", 1078 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", 1079 | "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=" 1080 | }, 1081 | "typedarray": { 1082 | "version": "0.0.6", 1083 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1084 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 1085 | "dev": true 1086 | }, 1087 | "unpipe": { 1088 | "version": "1.0.0", 1089 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1090 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1091 | }, 1092 | "user-home": { 1093 | "version": "2.0.0", 1094 | "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", 1095 | "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", 1096 | "dev": true 1097 | }, 1098 | "util-deprecate": { 1099 | "version": "1.0.2", 1100 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1101 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 1102 | "dev": true 1103 | }, 1104 | "utils-merge": { 1105 | "version": "1.0.0", 1106 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", 1107 | "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" 1108 | }, 1109 | "vary": { 1110 | "version": "1.1.1", 1111 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", 1112 | "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=" 1113 | }, 1114 | "wordwrap": { 1115 | "version": "1.0.0", 1116 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 1117 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", 1118 | "dev": true 1119 | }, 1120 | "wrappy": { 1121 | "version": "1.0.2", 1122 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1123 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1124 | "dev": true 1125 | }, 1126 | "write": { 1127 | "version": "0.2.1", 1128 | "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", 1129 | "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", 1130 | "dev": true 1131 | }, 1132 | "xtend": { 1133 | "version": "4.0.1", 1134 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 1135 | "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", 1136 | "dev": true 1137 | } 1138 | } 1139 | } 1140 | -------------------------------------------------------------------------------- /src/gateway/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gateway", 3 | "private": true, 4 | "version": "1.0.0", 5 | "description": "Introduction to Kubernetes with Node.js", 6 | "main": "index.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "lint": "eslint src" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/RisingStack/example-kubernetes-nodejs.git" 14 | }, 15 | "author": "RisingStack, Inc.", 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/RisingStack/example-kubernetes-nodejs/issues" 19 | }, 20 | "homepage": "https://github.com/RisingStack/example-kubernetes-nodejs#readme", 21 | "devDependencies": { 22 | "eslint": "3.19.0", 23 | "eslint-config-airbnb-base": "11.2.0", 24 | "eslint-plugin-import": "2.2.0", 25 | "eslint-plugin-promise": "3.5.0" 26 | }, 27 | "dependencies": { 28 | "express": "4.15.3" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/gateway/server.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const crypto = require('crypto') 4 | const express = require('express') 5 | 6 | const app = express() 7 | const port = process.env.PORT || 3001 8 | const secret = 'abcdefg' 9 | 10 | const server = app.listen(port, (err) => { 11 | if (err) { 12 | console.error(err) 13 | process.exit(1) 14 | } 15 | 16 | console.log(`Server is listening on ${port} port`) 17 | }) 18 | 19 | app.get('/', (req, res) => { 20 | res.json({ service: 'gateway' }) 21 | }) 22 | 23 | app.get('/load', (req, res) => { 24 | const hash = crypto.createHmac('sha256', secret) 25 | .update('I love cupcakes') 26 | .digest('hex') 27 | 28 | res.json({ hash }) 29 | }) 30 | 31 | app.get('/secret', (req, res) => { 32 | res.json({ secret: process.env.MY_SECRET }) 33 | }) 34 | 35 | app.get('/healthz', (req, res) => { 36 | res.end() 37 | }) 38 | 39 | process.on('SIGTERM', () => { 40 | server.close((err) => { 41 | console.error(err) 42 | process.exit(1) 43 | }) 44 | 45 | process.exit(0) 46 | }) 47 | --------------------------------------------------------------------------------