├── .dockerignore ├── .env.sample ├── .gitignore ├── .prettierrc.yml ├── .sequelizerc ├── Dockerfile ├── README.md ├── docker-compose.yml ├── docs └── google-calendar.md ├── package-lock.json ├── package.json ├── sequelize ├── cli.js └── migrations │ ├── 20180610013241-meta.js │ ├── 20180610013915-events.js │ └── 20180610014533-events.js └── src ├── batch.js ├── garoon.js ├── google-calendar.js ├── index.js ├── server.js └── store.js /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | # Garoon 2 | ## GaroonのURL 3 | GAROON_URL= 4 | ## Garoonの個人のuid 5 | ## user_view.csp?uid=xxxx 6 | GAROON_MY_ID= 7 | ## ログイン名 8 | GAROON_MY_NAME= 9 | ## ログインパスワード 10 | GAROON_MY_PASSWORD= 11 | 12 | # Google Calendar 13 | CALENDAR_ID= 14 | SERVICE_ACCT_ID=xxxx@yyyy-zzzzz.iam.gserviceaccount.com 15 | GOOGLE_API_KEY_FILE=google-api-key.json 16 | ## webhookのcallback用URL 17 | CALLBACK_URL= 18 | 19 | # App 20 | ## Planのフィルタリング (複数の場合はカンマ区切りで) 21 | PLAN_FILTER=休み 22 | ## 何日先までGaroonから情報を取得するか 23 | TERM=10 24 | ## デフォルトでは、Google Calendarからイベントを削除しても複数人のGaroonのイベントは消さない 25 | SAFETY=true 26 | ## fetchする繰り返し区間 27 | CRON=00 */15 * * * * 28 | 29 | # DB 30 | MYSQL_ROOT_PASSWORD= 31 | MYSQL_DATABASE=garoogle 32 | MYSQL_USER= 33 | MYSQL_PASSWORD= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | GGsync* 4 | data 5 | client_secret.json 6 | google-api-key.json -------------------------------------------------------------------------------- /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | printWidth: 100 2 | singleQuote: true 3 | arrowParens: always -------------------------------------------------------------------------------- /.sequelizerc: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | config: path.resolve('sequelize', 'cli.js'), 7 | 'migrations-path': path.resolve('sequelize', 'migrations') 8 | }; -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:10.2.1 2 | 3 | WORKDIR /app 4 | COPY . . 5 | 6 | RUN npx npm install 7 | 8 | ENV HOST=0.0.0.0 9 | 10 | COPY . /app 11 | 12 | ENTRYPOINT ["npx", "npm", "run"] 13 | CMD ["start"] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # garoogle 2 | 3 | Garoon と Google Calendar を双方向に同期します。 4 | 5 | ## Setup 6 | 7 | ```sh 8 | $ git clone git@github.com:hiroppy/garoogle.git 9 | $ cd garoogle 10 | $ npm install --production 11 | $ cp .env.sample .env # and edit 12 | $ docker-compose run app migrate 13 | $ docker-compose up -d 14 | ``` 15 | 16 | Google Calendar の設定は[こちら](./docs/google-calendar.md) 17 | 18 | ## API 19 | 20 | ### health 21 | 22 | `/api/health` 23 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | app: 5 | depends_on: 6 | - mysql 7 | build: 8 | context: '.' 9 | ports: 10 | - '3000:3000' 11 | volumes: 12 | - '.:/app' 13 | env_file: 14 | - .env 15 | batch: 16 | build: 17 | context: '.' 18 | volumes: 19 | - '.:/app' 20 | env_file: 21 | - .env 22 | command: start:batch 23 | mysql: 24 | image: mysql:5.7 # wait for https://github.com/mysqljs/mysql/pull/1962 25 | volumes: 26 | - ./data/db:/var/lib/mysql 27 | env_file: 28 | - .env 29 | # redis: 30 | # image: 'redis:3.2-alpine' 31 | # command: redis-server --appendonly yes 32 | # volumes: 33 | # - 'redis:/data' -------------------------------------------------------------------------------- /docs/google-calendar.md: -------------------------------------------------------------------------------- 1 | # Google Calendar の設定 2 | 3 | ## 必要な環境変数 4 | 5 | `CALENDAR_ID`, `SERVICE_ACCT_ID`, `GOOGLE_API_KEY_FILE` 6 | 7 | ## Google API の利用設定 8 | 9 | https://console.developers.google.com/cloud-resource-manager 10 | 11 | 1. プロジェクトを作成 12 | 2. 認証情報のページへ行く https://console.developers.google.com/apis/credentials?project=xxxx 13 | 3. 認証情報を作成 -> サービスアカウントキー 14 | 4. `役割なし` でサービスアカウントを選択し、JSON でダウンロード 15 | 5. `GOOGLE_API_KEY_FILE`のパスをこのファイルのパスへ変更 16 | 6. ライブラリのページへ行く https://console.developers.google.com/apis/library?project=xxxx 17 | 7. Google Calendar API を検索し、有効にする 18 | 19 | ## カレンダーを作成する 20 | 21 | https://calendar.google.com/calendar 22 | 23 | 1. Garoon と同期されるカレンダーを用意する 24 | 2. 作ったら、左のサイドメニューのマイカレンダーからそのカレンダーの設定(設定と共有)を開く 25 | 3. カレンダーの統合からカレンダー ID を取得 26 | 4. `CALENDAR_ID`の名前を 3 で取得した名前にする(e.g. `xxx@group.calendar.google.com`) 27 | 5. カレンダーの設定の `特定のユーザーとの共有` からサービスアカウントのメールアドレスを追加し、予定の変更権限を付与する 28 | 29 | # 補足 30 | 31 | 以下の記事を参考にしてください。 32 | [Google カレンダー連携 - Garoon の予定を Google カレンダーに表示 -](https://developer.cybozu.io/hc/ja/articles/204426680-Google%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC%E9%80%A3%E6%90%BA-Garoon%E3%81%AE%E4%BA%88%E5%AE%9A%E3%82%92Google%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC%E3%81%AB%E8%A1%A8%E7%A4%BA-) 33 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "garoogle", 3 | "version": "1.1.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@about_hiroppy/node-google-calendar": { 8 | "version": "1.1.2", 9 | "resolved": 10 | "https://registry.npmjs.org/@about_hiroppy/node-google-calendar/-/node-google-calendar-1.1.2.tgz", 11 | "integrity": 12 | "sha512-jo0L8UV0jQxPHwe6ZiHtkgSaRDI1pey/pjvCMP1v6kzNdi1UsZQeu4rLIBLyn/AR1ZShpwLseHIanp0LYWN29g==", 13 | "requires": { 14 | "bluebird": "3.5.1", 15 | "google-oauth-jwt": "0.2.0", 16 | "request-promise": "4.2.2" 17 | } 18 | }, 19 | "@types/geojson": { 20 | "version": "1.0.6", 21 | "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-1.0.6.tgz", 22 | "integrity": 23 | "sha512-Xqg/lIZMrUd0VRmSRbCAewtwGZiAk3mEUDvV4op1tGl+LvyPcb/MIOSxTl9z+9+J+R4/vpjiCAT4xeKzH9ji1w==" 24 | }, 25 | "@types/node": { 26 | "version": "10.1.3", 27 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.1.3.tgz", 28 | "integrity": 29 | "sha512-GiCx7dRvta0hbxXoJFAUxz+CKX6bZSCKjM5slq2vPp/5zwK01T4ibYZkGr6EN4F2QmxDQR76/ZHg6q+7iFWCWw==" 30 | }, 31 | "abbrev": { 32 | "version": "1.1.1", 33 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 34 | "integrity": 35 | "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" 36 | }, 37 | "accepts": { 38 | "version": "1.3.5", 39 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", 40 | "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", 41 | "requires": { 42 | "mime-types": "2.1.18", 43 | "negotiator": "0.6.1" 44 | } 45 | }, 46 | "ajv": { 47 | "version": "5.5.2", 48 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", 49 | "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", 50 | "requires": { 51 | "co": "4.6.0", 52 | "fast-deep-equal": "1.1.0", 53 | "fast-json-stable-stringify": "2.0.0", 54 | "json-schema-traverse": "0.3.1" 55 | } 56 | }, 57 | "ansi-regex": { 58 | "version": "2.1.1", 59 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 60 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 61 | }, 62 | "ansi-styles": { 63 | "version": "3.2.1", 64 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 65 | "integrity": 66 | "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 67 | "dev": true, 68 | "requires": { 69 | "color-convert": "1.9.1" 70 | } 71 | }, 72 | "ansicolors": { 73 | "version": "0.2.1", 74 | "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz", 75 | "integrity": "sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8=" 76 | }, 77 | "array-flatten": { 78 | "version": "1.1.1", 79 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 80 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 81 | }, 82 | "asn1": { 83 | "version": "0.2.3", 84 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", 85 | "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" 86 | }, 87 | "assert-plus": { 88 | "version": "1.0.0", 89 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 90 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 91 | }, 92 | "asynckit": { 93 | "version": "0.4.0", 94 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 95 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 96 | }, 97 | "aws-sign2": { 98 | "version": "0.7.0", 99 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 100 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 101 | }, 102 | "aws4": { 103 | "version": "1.7.0", 104 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", 105 | "integrity": 106 | "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" 107 | }, 108 | "babel-runtime": { 109 | "version": "6.26.0", 110 | "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", 111 | "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", 112 | "requires": { 113 | "core-js": "2.5.7", 114 | "regenerator-runtime": "0.11.1" 115 | } 116 | }, 117 | "bcrypt-pbkdf": { 118 | "version": "1.0.1", 119 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", 120 | "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", 121 | "optional": true, 122 | "requires": { 123 | "tweetnacl": "0.14.5" 124 | } 125 | }, 126 | "bluebird": { 127 | "version": "3.5.1", 128 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", 129 | "integrity": 130 | "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" 131 | }, 132 | "body-parser": { 133 | "version": "1.18.3", 134 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", 135 | "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", 136 | "requires": { 137 | "bytes": "3.0.0", 138 | "content-type": "1.0.4", 139 | "debug": "2.6.9", 140 | "depd": "1.1.2", 141 | "http-errors": "1.6.3", 142 | "iconv-lite": "0.4.23", 143 | "on-finished": "2.3.0", 144 | "qs": "6.5.2", 145 | "raw-body": "2.3.3", 146 | "type-is": "1.6.16" 147 | } 148 | }, 149 | "builtin-modules": { 150 | "version": "1.1.1", 151 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 152 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" 153 | }, 154 | "bytes": { 155 | "version": "3.0.0", 156 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 157 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 158 | }, 159 | "camelcase": { 160 | "version": "4.1.0", 161 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", 162 | "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" 163 | }, 164 | "cardinal": { 165 | "version": "1.0.0", 166 | "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-1.0.0.tgz", 167 | "integrity": "sha1-UOIcGwqjdyn5N33vGWtanOyTLuk=", 168 | "requires": { 169 | "ansicolors": "0.2.1", 170 | "redeyed": "1.0.1" 171 | } 172 | }, 173 | "caseless": { 174 | "version": "0.12.0", 175 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 176 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 177 | }, 178 | "chalk": { 179 | "version": "2.4.1", 180 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 181 | "integrity": 182 | "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 183 | "dev": true, 184 | "requires": { 185 | "ansi-styles": "3.2.1", 186 | "escape-string-regexp": "1.0.5", 187 | "supports-color": "5.4.0" 188 | } 189 | }, 190 | "ci-info": { 191 | "version": "1.1.3", 192 | "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.3.tgz", 193 | "integrity": 194 | "sha512-SK/846h/Rcy8q9Z9CAwGBLfCJ6EkjJWdpelWDufQpqVDYq2Wnnv8zlSO6AMQap02jvhVruKKpEtQOufo3pFhLg==", 195 | "dev": true 196 | }, 197 | "cli-color": { 198 | "version": "1.2.0", 199 | "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.2.0.tgz", 200 | "integrity": "sha1-OlrnT9drYmevZm5p4q+70B3vNNE=", 201 | "requires": { 202 | "ansi-regex": "2.1.1", 203 | "d": "1.0.0", 204 | "es5-ext": "0.10.45", 205 | "es6-iterator": "2.0.3", 206 | "memoizee": "0.4.12", 207 | "timers-ext": "0.1.5" 208 | } 209 | }, 210 | "cliui": { 211 | "version": "3.2.0", 212 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", 213 | "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", 214 | "requires": { 215 | "string-width": "1.0.2", 216 | "strip-ansi": "3.0.1", 217 | "wrap-ansi": "2.1.0" 218 | }, 219 | "dependencies": { 220 | "string-width": { 221 | "version": "1.0.2", 222 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 223 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 224 | "requires": { 225 | "code-point-at": "1.1.0", 226 | "is-fullwidth-code-point": "1.0.0", 227 | "strip-ansi": "3.0.1" 228 | } 229 | } 230 | } 231 | }, 232 | "cls-bluebird": { 233 | "version": "2.1.0", 234 | "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", 235 | "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=", 236 | "requires": { 237 | "is-bluebird": "1.0.2", 238 | "shimmer": "1.2.0" 239 | } 240 | }, 241 | "co": { 242 | "version": "4.6.0", 243 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 244 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" 245 | }, 246 | "code-point-at": { 247 | "version": "1.1.0", 248 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 249 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" 250 | }, 251 | "color-convert": { 252 | "version": "1.9.1", 253 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", 254 | "integrity": 255 | "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", 256 | "dev": true, 257 | "requires": { 258 | "color-name": "1.1.3" 259 | } 260 | }, 261 | "color-name": { 262 | "version": "1.1.3", 263 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 264 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 265 | "dev": true 266 | }, 267 | "combined-stream": { 268 | "version": "1.0.6", 269 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", 270 | "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", 271 | "requires": { 272 | "delayed-stream": "1.0.0" 273 | } 274 | }, 275 | "commander": { 276 | "version": "2.15.1", 277 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", 278 | "integrity": 279 | "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" 280 | }, 281 | "config-chain": { 282 | "version": "1.1.11", 283 | "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", 284 | "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", 285 | "requires": { 286 | "ini": "1.3.5", 287 | "proto-list": "1.2.4" 288 | } 289 | }, 290 | "content-disposition": { 291 | "version": "0.5.2", 292 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 293 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 294 | }, 295 | "content-type": { 296 | "version": "1.0.4", 297 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 298 | "integrity": 299 | "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 300 | }, 301 | "cookie": { 302 | "version": "0.3.1", 303 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 304 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 305 | }, 306 | "cookie-signature": { 307 | "version": "1.0.6", 308 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 309 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 310 | }, 311 | "core-js": { 312 | "version": "2.5.7", 313 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", 314 | "integrity": 315 | "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" 316 | }, 317 | "core-util-is": { 318 | "version": "1.0.2", 319 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 320 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 321 | }, 322 | "cron": { 323 | "version": "1.3.0", 324 | "resolved": "https://registry.npmjs.org/cron/-/cron-1.3.0.tgz", 325 | "integrity": 326 | "sha512-K/SF7JlgMmNjcThWxkKvsHhey2EDB4CeOEWJ9aXWj3fbQJppsvTPIeyLdHfNq5IbbsMUUjRW1nr5dSO95f2E4w==", 327 | "requires": { 328 | "moment-timezone": "0.5.17" 329 | } 330 | }, 331 | "cross-spawn": { 332 | "version": "5.1.0", 333 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", 334 | "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", 335 | "requires": { 336 | "lru-cache": "4.1.3", 337 | "shebang-command": "1.2.0", 338 | "which": "1.3.1" 339 | } 340 | }, 341 | "d": { 342 | "version": "1.0.0", 343 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", 344 | "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", 345 | "requires": { 346 | "es5-ext": "0.10.45" 347 | } 348 | }, 349 | "dashdash": { 350 | "version": "1.14.1", 351 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 352 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 353 | "requires": { 354 | "assert-plus": "1.0.0" 355 | } 356 | }, 357 | "debug": { 358 | "version": "2.6.9", 359 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 360 | "integrity": 361 | "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 362 | "requires": { 363 | "ms": "2.0.0" 364 | } 365 | }, 366 | "decamelize": { 367 | "version": "1.2.0", 368 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 369 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 370 | }, 371 | "delayed-stream": { 372 | "version": "1.0.0", 373 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 374 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 375 | }, 376 | "denque": { 377 | "version": "1.2.3", 378 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.2.3.tgz", 379 | "integrity": 380 | "sha512-BOjyD1zPf7gqgXlXBCnCsz84cbRNfqpQNvWOUiw3Onu9s7a2afW2LyHzctoie/2KELfUoZkNHTnW02C3hCU20w==" 381 | }, 382 | "depd": { 383 | "version": "1.1.2", 384 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 385 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 386 | }, 387 | "destroy": { 388 | "version": "1.0.4", 389 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 390 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 391 | }, 392 | "dottie": { 393 | "version": "2.0.0", 394 | "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.0.tgz", 395 | "integrity": "sha1-2hkZgci41xPKARXViYzzl8Lw3dA=" 396 | }, 397 | "ecc-jsbn": { 398 | "version": "0.1.1", 399 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", 400 | "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", 401 | "optional": true, 402 | "requires": { 403 | "jsbn": "0.1.1" 404 | } 405 | }, 406 | "editorconfig": { 407 | "version": "0.13.3", 408 | "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.13.3.tgz", 409 | "integrity": 410 | "sha512-WkjsUNVCu+ITKDj73QDvi0trvpdDWdkDyHybDGSXPfekLCqwmpD7CP7iPbvBgosNuLcI96XTDwNa75JyFl7tEQ==", 411 | "requires": { 412 | "bluebird": "3.5.1", 413 | "commander": "2.15.1", 414 | "lru-cache": "3.2.0", 415 | "semver": "5.5.0", 416 | "sigmund": "1.0.1" 417 | }, 418 | "dependencies": { 419 | "lru-cache": { 420 | "version": "3.2.0", 421 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", 422 | "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", 423 | "requires": { 424 | "pseudomap": "1.0.2" 425 | } 426 | } 427 | } 428 | }, 429 | "ee-first": { 430 | "version": "1.1.1", 431 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 432 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 433 | }, 434 | "encodeurl": { 435 | "version": "1.0.2", 436 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 437 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 438 | }, 439 | "encoding": { 440 | "version": "0.1.12", 441 | "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", 442 | "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", 443 | "requires": { 444 | "iconv-lite": "0.4.23" 445 | } 446 | }, 447 | "error-ex": { 448 | "version": "1.3.1", 449 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", 450 | "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", 451 | "requires": { 452 | "is-arrayish": "0.2.1" 453 | } 454 | }, 455 | "es5-ext": { 456 | "version": "0.10.45", 457 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", 458 | "integrity": 459 | "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", 460 | "requires": { 461 | "es6-iterator": "2.0.3", 462 | "es6-symbol": "3.1.1", 463 | "next-tick": "1.0.0" 464 | } 465 | }, 466 | "es6-iterator": { 467 | "version": "2.0.3", 468 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", 469 | "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", 470 | "requires": { 471 | "d": "1.0.0", 472 | "es5-ext": "0.10.45", 473 | "es6-symbol": "3.1.1" 474 | } 475 | }, 476 | "es6-promise": { 477 | "version": "4.2.4", 478 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", 479 | "integrity": 480 | "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==" 481 | }, 482 | "es6-symbol": { 483 | "version": "3.1.1", 484 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", 485 | "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", 486 | "requires": { 487 | "d": "1.0.0", 488 | "es5-ext": "0.10.45" 489 | } 490 | }, 491 | "es6-weak-map": { 492 | "version": "2.0.2", 493 | "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", 494 | "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", 495 | "requires": { 496 | "d": "1.0.0", 497 | "es5-ext": "0.10.45", 498 | "es6-iterator": "2.0.3", 499 | "es6-symbol": "3.1.1" 500 | } 501 | }, 502 | "escape-html": { 503 | "version": "1.0.3", 504 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 505 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 506 | }, 507 | "escape-string-regexp": { 508 | "version": "1.0.5", 509 | "resolved": 510 | "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 511 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 512 | "dev": true 513 | }, 514 | "esprima": { 515 | "version": "3.0.0", 516 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.0.0.tgz", 517 | "integrity": "sha1-U88kes2ncxPlUcOqLnM0LT+099k=" 518 | }, 519 | "etag": { 520 | "version": "1.8.1", 521 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 522 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 523 | }, 524 | "event-emitter": { 525 | "version": "0.3.5", 526 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", 527 | "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", 528 | "requires": { 529 | "d": "1.0.0", 530 | "es5-ext": "0.10.45" 531 | } 532 | }, 533 | "execa": { 534 | "version": "0.8.0", 535 | "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", 536 | "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", 537 | "dev": true, 538 | "requires": { 539 | "cross-spawn": "5.1.0", 540 | "get-stream": "3.0.0", 541 | "is-stream": "1.1.0", 542 | "npm-run-path": "2.0.2", 543 | "p-finally": "1.0.0", 544 | "signal-exit": "3.0.2", 545 | "strip-eof": "1.0.0" 546 | } 547 | }, 548 | "express": { 549 | "version": "4.16.3", 550 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", 551 | "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", 552 | "requires": { 553 | "accepts": "1.3.5", 554 | "array-flatten": "1.1.1", 555 | "body-parser": "1.18.2", 556 | "content-disposition": "0.5.2", 557 | "content-type": "1.0.4", 558 | "cookie": "0.3.1", 559 | "cookie-signature": "1.0.6", 560 | "debug": "2.6.9", 561 | "depd": "1.1.2", 562 | "encodeurl": "1.0.2", 563 | "escape-html": "1.0.3", 564 | "etag": "1.8.1", 565 | "finalhandler": "1.1.1", 566 | "fresh": "0.5.2", 567 | "merge-descriptors": "1.0.1", 568 | "methods": "1.1.2", 569 | "on-finished": "2.3.0", 570 | "parseurl": "1.3.2", 571 | "path-to-regexp": "0.1.7", 572 | "proxy-addr": "2.0.3", 573 | "qs": "6.5.1", 574 | "range-parser": "1.2.0", 575 | "safe-buffer": "5.1.1", 576 | "send": "0.16.2", 577 | "serve-static": "1.13.2", 578 | "setprototypeof": "1.1.0", 579 | "statuses": "1.4.0", 580 | "type-is": "1.6.16", 581 | "utils-merge": "1.0.1", 582 | "vary": "1.1.2" 583 | }, 584 | "dependencies": { 585 | "body-parser": { 586 | "version": "1.18.2", 587 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", 588 | "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", 589 | "requires": { 590 | "bytes": "3.0.0", 591 | "content-type": "1.0.4", 592 | "debug": "2.6.9", 593 | "depd": "1.1.2", 594 | "http-errors": "1.6.3", 595 | "iconv-lite": "0.4.19", 596 | "on-finished": "2.3.0", 597 | "qs": "6.5.1", 598 | "raw-body": "2.3.2", 599 | "type-is": "1.6.16" 600 | } 601 | }, 602 | "iconv-lite": { 603 | "version": "0.4.19", 604 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 605 | "integrity": 606 | "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" 607 | }, 608 | "qs": { 609 | "version": "6.5.1", 610 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", 611 | "integrity": 612 | "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" 613 | }, 614 | "raw-body": { 615 | "version": "2.3.2", 616 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 617 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 618 | "requires": { 619 | "bytes": "3.0.0", 620 | "http-errors": "1.6.2", 621 | "iconv-lite": "0.4.19", 622 | "unpipe": "1.0.0" 623 | }, 624 | "dependencies": { 625 | "depd": { 626 | "version": "1.1.1", 627 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 628 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 629 | }, 630 | "http-errors": { 631 | "version": "1.6.2", 632 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 633 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 634 | "requires": { 635 | "depd": "1.1.1", 636 | "inherits": "2.0.3", 637 | "setprototypeof": "1.0.3", 638 | "statuses": "1.4.0" 639 | } 640 | }, 641 | "setprototypeof": { 642 | "version": "1.0.3", 643 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 644 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 645 | } 646 | } 647 | }, 648 | "safe-buffer": { 649 | "version": "5.1.1", 650 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 651 | "integrity": 652 | "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 653 | }, 654 | "statuses": { 655 | "version": "1.4.0", 656 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 657 | "integrity": 658 | "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 659 | } 660 | } 661 | }, 662 | "extend": { 663 | "version": "3.0.1", 664 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", 665 | "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" 666 | }, 667 | "extsprintf": { 668 | "version": "1.3.0", 669 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 670 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 671 | }, 672 | "fast-deep-equal": { 673 | "version": "1.1.0", 674 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", 675 | "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" 676 | }, 677 | "fast-json-stable-stringify": { 678 | "version": "2.0.0", 679 | "resolved": 680 | "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 681 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" 682 | }, 683 | "finalhandler": { 684 | "version": "1.1.1", 685 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", 686 | "integrity": 687 | "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", 688 | "requires": { 689 | "debug": "2.6.9", 690 | "encodeurl": "1.0.2", 691 | "escape-html": "1.0.3", 692 | "on-finished": "2.3.0", 693 | "parseurl": "1.3.2", 694 | "statuses": "1.4.0", 695 | "unpipe": "1.0.0" 696 | }, 697 | "dependencies": { 698 | "statuses": { 699 | "version": "1.4.0", 700 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 701 | "integrity": 702 | "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 703 | } 704 | } 705 | }, 706 | "find-up": { 707 | "version": "2.1.0", 708 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", 709 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", 710 | "requires": { 711 | "locate-path": "2.0.0" 712 | } 713 | }, 714 | "forever-agent": { 715 | "version": "0.6.1", 716 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 717 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 718 | }, 719 | "form-data": { 720 | "version": "2.3.2", 721 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", 722 | "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", 723 | "requires": { 724 | "asynckit": "0.4.0", 725 | "combined-stream": "1.0.6", 726 | "mime-types": "2.1.18" 727 | } 728 | }, 729 | "forwarded": { 730 | "version": "0.1.2", 731 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 732 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 733 | }, 734 | "fresh": { 735 | "version": "0.5.2", 736 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 737 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 738 | }, 739 | "fs-extra": { 740 | "version": "5.0.0", 741 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", 742 | "integrity": 743 | "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", 744 | "requires": { 745 | "graceful-fs": "4.1.11", 746 | "jsonfile": "4.0.0", 747 | "universalify": "0.1.1" 748 | } 749 | }, 750 | "garoon-soap": { 751 | "version": "0.1.9", 752 | "resolved": "https://registry.npmjs.org/garoon-soap/-/garoon-soap-0.1.9.tgz", 753 | "integrity": "sha1-GVuJfqzKhXzqvp8ba418exgy38E=", 754 | "requires": { 755 | "es6-promise": "4.2.4", 756 | "node-fetch": "1.7.3", 757 | "xml": "1.0.1", 758 | "xml2js": "0.4.19" 759 | } 760 | }, 761 | "generate-function": { 762 | "version": "2.0.0", 763 | "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", 764 | "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=" 765 | }, 766 | "generic-pool": { 767 | "version": "3.4.2", 768 | "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.4.2.tgz", 769 | "integrity": 770 | "sha512-H7cUpwCQSiJmAHM4c/aFu6fUfrhWXW1ncyh8ftxEPMu6AiYkHw9K8br720TGPZJbk5eOH2bynjZD1yPvdDAmag==" 771 | }, 772 | "get-caller-file": { 773 | "version": "1.0.2", 774 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", 775 | "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" 776 | }, 777 | "get-stream": { 778 | "version": "3.0.0", 779 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", 780 | "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" 781 | }, 782 | "getpass": { 783 | "version": "0.1.7", 784 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 785 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 786 | "requires": { 787 | "assert-plus": "1.0.0" 788 | } 789 | }, 790 | "google-oauth-jwt": { 791 | "version": "0.2.0", 792 | "resolved": "https://registry.npmjs.org/google-oauth-jwt/-/google-oauth-jwt-0.2.0.tgz", 793 | "integrity": "sha1-SPV2LQzBFjzyajB2SMghdLaulOc=", 794 | "requires": { 795 | "debug": "2.6.9", 796 | "request": "2.87.0" 797 | } 798 | }, 799 | "graceful-fs": { 800 | "version": "4.1.11", 801 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 802 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" 803 | }, 804 | "har-schema": { 805 | "version": "2.0.0", 806 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 807 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 808 | }, 809 | "har-validator": { 810 | "version": "5.0.3", 811 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", 812 | "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", 813 | "requires": { 814 | "ajv": "5.5.2", 815 | "har-schema": "2.0.0" 816 | } 817 | }, 818 | "has-flag": { 819 | "version": "3.0.0", 820 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 821 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 822 | "dev": true 823 | }, 824 | "hosted-git-info": { 825 | "version": "2.6.0", 826 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", 827 | "integrity": 828 | "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==" 829 | }, 830 | "http-errors": { 831 | "version": "1.6.3", 832 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", 833 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", 834 | "requires": { 835 | "depd": "1.1.2", 836 | "inherits": "2.0.3", 837 | "setprototypeof": "1.1.0", 838 | "statuses": "1.5.0" 839 | } 840 | }, 841 | "http-signature": { 842 | "version": "1.2.0", 843 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 844 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 845 | "requires": { 846 | "assert-plus": "1.0.0", 847 | "jsprim": "1.4.1", 848 | "sshpk": "1.14.1" 849 | } 850 | }, 851 | "husky": { 852 | "version": "0.14.3", 853 | "resolved": "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz", 854 | "integrity": 855 | "sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA==", 856 | "dev": true, 857 | "requires": { 858 | "is-ci": "1.1.0", 859 | "normalize-path": "1.0.0", 860 | "strip-indent": "2.0.0" 861 | } 862 | }, 863 | "iconv-lite": { 864 | "version": "0.4.23", 865 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", 866 | "integrity": 867 | "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", 868 | "requires": { 869 | "safer-buffer": "2.1.2" 870 | } 871 | }, 872 | "ignore": { 873 | "version": "3.3.8", 874 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz", 875 | "integrity": 876 | "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==", 877 | "dev": true 878 | }, 879 | "inflection": { 880 | "version": "1.12.0", 881 | "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", 882 | "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" 883 | }, 884 | "inherits": { 885 | "version": "2.0.3", 886 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 887 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 888 | }, 889 | "ini": { 890 | "version": "1.3.5", 891 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", 892 | "integrity": 893 | "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" 894 | }, 895 | "invert-kv": { 896 | "version": "1.0.0", 897 | "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", 898 | "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" 899 | }, 900 | "ipaddr.js": { 901 | "version": "1.6.0", 902 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", 903 | "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" 904 | }, 905 | "is-arrayish": { 906 | "version": "0.2.1", 907 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 908 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" 909 | }, 910 | "is-bluebird": { 911 | "version": "1.0.2", 912 | "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", 913 | "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI=" 914 | }, 915 | "is-builtin-module": { 916 | "version": "1.0.0", 917 | "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", 918 | "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", 919 | "requires": { 920 | "builtin-modules": "1.1.1" 921 | } 922 | }, 923 | "is-ci": { 924 | "version": "1.1.0", 925 | "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz", 926 | "integrity": 927 | "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", 928 | "dev": true, 929 | "requires": { 930 | "ci-info": "1.1.3" 931 | } 932 | }, 933 | "is-fullwidth-code-point": { 934 | "version": "1.0.0", 935 | "resolved": 936 | "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 937 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 938 | "requires": { 939 | "number-is-nan": "1.0.1" 940 | } 941 | }, 942 | "is-promise": { 943 | "version": "2.1.0", 944 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 945 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 946 | }, 947 | "is-stream": { 948 | "version": "1.1.0", 949 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 950 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 951 | }, 952 | "is-typedarray": { 953 | "version": "1.0.0", 954 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 955 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 956 | }, 957 | "isarray": { 958 | "version": "1.0.0", 959 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 960 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 961 | }, 962 | "isexe": { 963 | "version": "2.0.0", 964 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 965 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 966 | }, 967 | "isstream": { 968 | "version": "0.1.2", 969 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 970 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 971 | }, 972 | "js-beautify": { 973 | "version": "1.7.5", 974 | "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.7.5.tgz", 975 | "integrity": 976 | "sha512-9OhfAqGOrD7hoQBLJMTA+BKuKmoEtTJXzZ7WDF/9gvjtey1koVLuZqIY6c51aPDjbNdNtIXAkiWKVhziawE9Og==", 977 | "requires": { 978 | "config-chain": "1.1.11", 979 | "editorconfig": "0.13.3", 980 | "mkdirp": "0.5.1", 981 | "nopt": "3.0.6" 982 | } 983 | }, 984 | "jsbn": { 985 | "version": "0.1.1", 986 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 987 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 988 | "optional": true 989 | }, 990 | "json-schema": { 991 | "version": "0.2.3", 992 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 993 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 994 | }, 995 | "json-schema-traverse": { 996 | "version": "0.3.1", 997 | "resolved": 998 | "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", 999 | "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" 1000 | }, 1001 | "json-stringify-safe": { 1002 | "version": "5.0.1", 1003 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1004 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 1005 | }, 1006 | "jsonfile": { 1007 | "version": "4.0.0", 1008 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", 1009 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", 1010 | "requires": { 1011 | "graceful-fs": "4.1.11" 1012 | } 1013 | }, 1014 | "jsprim": { 1015 | "version": "1.4.1", 1016 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 1017 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 1018 | "requires": { 1019 | "assert-plus": "1.0.0", 1020 | "extsprintf": "1.3.0", 1021 | "json-schema": "0.2.3", 1022 | "verror": "1.10.0" 1023 | } 1024 | }, 1025 | "lcid": { 1026 | "version": "1.0.0", 1027 | "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", 1028 | "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", 1029 | "requires": { 1030 | "invert-kv": "1.0.0" 1031 | } 1032 | }, 1033 | "load-json-file": { 1034 | "version": "2.0.0", 1035 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", 1036 | "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", 1037 | "requires": { 1038 | "graceful-fs": "4.1.11", 1039 | "parse-json": "2.2.0", 1040 | "pify": "2.3.0", 1041 | "strip-bom": "3.0.0" 1042 | } 1043 | }, 1044 | "locate-path": { 1045 | "version": "2.0.0", 1046 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", 1047 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", 1048 | "requires": { 1049 | "p-locate": "2.0.0", 1050 | "path-exists": "3.0.0" 1051 | } 1052 | }, 1053 | "lodash": { 1054 | "version": "4.17.10", 1055 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", 1056 | "integrity": 1057 | "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" 1058 | }, 1059 | "lodash.xor": { 1060 | "version": "4.5.0", 1061 | "resolved": "https://registry.npmjs.org/lodash.xor/-/lodash.xor-4.5.0.tgz", 1062 | "integrity": "sha1-TUjtfpgJWwYyWCunFNP/iuj7HbY=" 1063 | }, 1064 | "long": { 1065 | "version": "4.0.0", 1066 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 1067 | "integrity": 1068 | "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 1069 | }, 1070 | "lru-cache": { 1071 | "version": "4.1.3", 1072 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", 1073 | "integrity": 1074 | "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", 1075 | "requires": { 1076 | "pseudomap": "1.0.2", 1077 | "yallist": "2.1.2" 1078 | } 1079 | }, 1080 | "lru-queue": { 1081 | "version": "0.1.0", 1082 | "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", 1083 | "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", 1084 | "requires": { 1085 | "es5-ext": "0.10.45" 1086 | } 1087 | }, 1088 | "media-typer": { 1089 | "version": "0.3.0", 1090 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1091 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 1092 | }, 1093 | "mem": { 1094 | "version": "1.1.0", 1095 | "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", 1096 | "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", 1097 | "requires": { 1098 | "mimic-fn": "1.2.0" 1099 | } 1100 | }, 1101 | "memoizee": { 1102 | "version": "0.4.12", 1103 | "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.12.tgz", 1104 | "integrity": 1105 | "sha512-sprBu6nwxBWBvBOh5v2jcsGqiGLlL2xr2dLub3vR8dnE8YB17omwtm/0NSHl8jjNbcsJd5GMWJAnTSVe/O0Wfg==", 1106 | "requires": { 1107 | "d": "1.0.0", 1108 | "es5-ext": "0.10.45", 1109 | "es6-weak-map": "2.0.2", 1110 | "event-emitter": "0.3.5", 1111 | "is-promise": "2.1.0", 1112 | "lru-queue": "0.1.0", 1113 | "next-tick": "1.0.0", 1114 | "timers-ext": "0.1.5" 1115 | } 1116 | }, 1117 | "merge-descriptors": { 1118 | "version": "1.0.1", 1119 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 1120 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 1121 | }, 1122 | "methods": { 1123 | "version": "1.1.2", 1124 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1125 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 1126 | }, 1127 | "mime": { 1128 | "version": "1.4.1", 1129 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", 1130 | "integrity": 1131 | "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" 1132 | }, 1133 | "mime-db": { 1134 | "version": "1.33.0", 1135 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", 1136 | "integrity": 1137 | "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" 1138 | }, 1139 | "mime-types": { 1140 | "version": "2.1.18", 1141 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", 1142 | "integrity": 1143 | "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", 1144 | "requires": { 1145 | "mime-db": "1.33.0" 1146 | } 1147 | }, 1148 | "mimic-fn": { 1149 | "version": "1.2.0", 1150 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 1151 | "integrity": 1152 | "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" 1153 | }, 1154 | "minimist": { 1155 | "version": "0.0.8", 1156 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1157 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 1158 | }, 1159 | "mkdirp": { 1160 | "version": "0.5.1", 1161 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1162 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1163 | "requires": { 1164 | "minimist": "0.0.8" 1165 | } 1166 | }, 1167 | "moment": { 1168 | "version": "2.22.1", 1169 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz", 1170 | "integrity": 1171 | "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ==" 1172 | }, 1173 | "moment-timezone": { 1174 | "version": "0.5.17", 1175 | "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.17.tgz", 1176 | "integrity": 1177 | "sha512-Y/JpVEWIOA9Gho4vO15MTnW1FCmHi3ypprrkUaxsZ1TKg3uqC8q/qMBjTddkHoiwwZN3qvZSr4zJP7x9V3LpXA==", 1178 | "requires": { 1179 | "moment": "2.22.1" 1180 | } 1181 | }, 1182 | "mri": { 1183 | "version": "1.1.1", 1184 | "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.1.tgz", 1185 | "integrity": "sha1-haom09ru7t+A3FmEr5XMXKXK2fE=", 1186 | "dev": true 1187 | }, 1188 | "ms": { 1189 | "version": "2.0.0", 1190 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1191 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1192 | }, 1193 | "mysql2": { 1194 | "version": "1.5.3", 1195 | "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.5.3.tgz", 1196 | "integrity": 1197 | "sha512-Oov36YQSeciNP9SeqE7je4eWgeGADOorXLmsqhtxOJmPGUOJSNJT0s6/eq1Byy4nhXTRQUvlMHsI4Q/eMEs88Q==", 1198 | "requires": { 1199 | "cardinal": "1.0.0", 1200 | "denque": "1.2.3", 1201 | "generate-function": "2.0.0", 1202 | "iconv-lite": "0.4.23", 1203 | "long": "4.0.0", 1204 | "lru-cache": "4.1.1", 1205 | "named-placeholders": "1.1.1", 1206 | "object-assign": "4.1.1", 1207 | "readable-stream": "2.3.5", 1208 | "safe-buffer": "5.1.2", 1209 | "seq-queue": "0.0.5", 1210 | "sqlstring": "2.3.1" 1211 | }, 1212 | "dependencies": { 1213 | "lru-cache": { 1214 | "version": "4.1.1", 1215 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", 1216 | "integrity": 1217 | "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", 1218 | "requires": { 1219 | "pseudomap": "1.0.2", 1220 | "yallist": "2.1.2" 1221 | } 1222 | } 1223 | } 1224 | }, 1225 | "named-placeholders": { 1226 | "version": "1.1.1", 1227 | "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.1.tgz", 1228 | "integrity": "sha1-O3oNJiA910s6nfTJz7gnsvuQfmQ=", 1229 | "requires": { 1230 | "lru-cache": "2.5.0" 1231 | }, 1232 | "dependencies": { 1233 | "lru-cache": { 1234 | "version": "2.5.0", 1235 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", 1236 | "integrity": "sha1-2COIrpyWC+y+oMc7uet5tsbOmus=" 1237 | } 1238 | } 1239 | }, 1240 | "negotiator": { 1241 | "version": "0.6.1", 1242 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 1243 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 1244 | }, 1245 | "next-tick": { 1246 | "version": "1.0.0", 1247 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", 1248 | "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" 1249 | }, 1250 | "node-fetch": { 1251 | "version": "1.7.3", 1252 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", 1253 | "integrity": 1254 | "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", 1255 | "requires": { 1256 | "encoding": "0.1.12", 1257 | "is-stream": "1.1.0" 1258 | } 1259 | }, 1260 | "nopt": { 1261 | "version": "3.0.6", 1262 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", 1263 | "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", 1264 | "requires": { 1265 | "abbrev": "1.1.1" 1266 | } 1267 | }, 1268 | "normalize-package-data": { 1269 | "version": "2.4.0", 1270 | "resolved": 1271 | "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", 1272 | "integrity": 1273 | "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", 1274 | "requires": { 1275 | "hosted-git-info": "2.6.0", 1276 | "is-builtin-module": "1.0.0", 1277 | "semver": "5.5.0", 1278 | "validate-npm-package-license": "3.0.3" 1279 | } 1280 | }, 1281 | "normalize-path": { 1282 | "version": "1.0.0", 1283 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", 1284 | "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", 1285 | "dev": true 1286 | }, 1287 | "npm-run-path": { 1288 | "version": "2.0.2", 1289 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", 1290 | "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", 1291 | "requires": { 1292 | "path-key": "2.0.1" 1293 | } 1294 | }, 1295 | "number-is-nan": { 1296 | "version": "1.0.1", 1297 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 1298 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" 1299 | }, 1300 | "oauth-sign": { 1301 | "version": "0.8.2", 1302 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", 1303 | "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" 1304 | }, 1305 | "object-assign": { 1306 | "version": "4.1.1", 1307 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1308 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 1309 | }, 1310 | "on-finished": { 1311 | "version": "2.3.0", 1312 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1313 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 1314 | "requires": { 1315 | "ee-first": "1.1.1" 1316 | } 1317 | }, 1318 | "os-locale": { 1319 | "version": "2.1.0", 1320 | "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", 1321 | "integrity": 1322 | "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", 1323 | "requires": { 1324 | "execa": "0.7.0", 1325 | "lcid": "1.0.0", 1326 | "mem": "1.1.0" 1327 | }, 1328 | "dependencies": { 1329 | "execa": { 1330 | "version": "0.7.0", 1331 | "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", 1332 | "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", 1333 | "requires": { 1334 | "cross-spawn": "5.1.0", 1335 | "get-stream": "3.0.0", 1336 | "is-stream": "1.1.0", 1337 | "npm-run-path": "2.0.2", 1338 | "p-finally": "1.0.0", 1339 | "signal-exit": "3.0.2", 1340 | "strip-eof": "1.0.0" 1341 | } 1342 | } 1343 | } 1344 | }, 1345 | "p-finally": { 1346 | "version": "1.0.0", 1347 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 1348 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" 1349 | }, 1350 | "p-limit": { 1351 | "version": "1.2.0", 1352 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", 1353 | "integrity": 1354 | "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", 1355 | "requires": { 1356 | "p-try": "1.0.0" 1357 | } 1358 | }, 1359 | "p-locate": { 1360 | "version": "2.0.0", 1361 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", 1362 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", 1363 | "requires": { 1364 | "p-limit": "1.2.0" 1365 | } 1366 | }, 1367 | "p-try": { 1368 | "version": "1.0.0", 1369 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", 1370 | "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" 1371 | }, 1372 | "parse-json": { 1373 | "version": "2.2.0", 1374 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", 1375 | "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", 1376 | "requires": { 1377 | "error-ex": "1.3.1" 1378 | } 1379 | }, 1380 | "parseurl": { 1381 | "version": "1.3.2", 1382 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 1383 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 1384 | }, 1385 | "path-exists": { 1386 | "version": "3.0.0", 1387 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1388 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" 1389 | }, 1390 | "path-key": { 1391 | "version": "2.0.1", 1392 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 1393 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" 1394 | }, 1395 | "path-parse": { 1396 | "version": "1.0.5", 1397 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", 1398 | "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" 1399 | }, 1400 | "path-to-regexp": { 1401 | "version": "0.1.7", 1402 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1403 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 1404 | }, 1405 | "path-type": { 1406 | "version": "2.0.0", 1407 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", 1408 | "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", 1409 | "requires": { 1410 | "pify": "2.3.0" 1411 | } 1412 | }, 1413 | "performance-now": { 1414 | "version": "2.1.0", 1415 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1416 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 1417 | }, 1418 | "pify": { 1419 | "version": "2.3.0", 1420 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1421 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" 1422 | }, 1423 | "prettier": { 1424 | "version": "1.13.4", 1425 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.13.4.tgz", 1426 | "integrity": 1427 | "sha512-emsEZ2bAigL1lq6ssgkpPm1MIBqgeTvcp90NxOP5XDqprub/V/WS2Hfgih3mS7/1dqTUvhG+sxx1Dv8crnVexA==", 1428 | "dev": true 1429 | }, 1430 | "pretty-quick": { 1431 | "version": "1.6.0", 1432 | "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-1.6.0.tgz", 1433 | "integrity": 1434 | "sha512-bnCmsPy98ERD7VWBO+0y1OGWLfx/DPUjNFN2ZRVyxuGBiic1BXAGgjHsTKgBIbPISdqpP6KBEmRV0Lir4xu/BA==", 1435 | "dev": true, 1436 | "requires": { 1437 | "chalk": "2.4.1", 1438 | "execa": "0.8.0", 1439 | "find-up": "2.1.0", 1440 | "ignore": "3.3.8", 1441 | "mri": "1.1.1" 1442 | } 1443 | }, 1444 | "process-nextick-args": { 1445 | "version": "2.0.0", 1446 | "resolved": 1447 | "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 1448 | "integrity": 1449 | "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" 1450 | }, 1451 | "proto-list": { 1452 | "version": "1.2.4", 1453 | "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", 1454 | "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" 1455 | }, 1456 | "proxy-addr": { 1457 | "version": "2.0.3", 1458 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", 1459 | "integrity": 1460 | "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", 1461 | "requires": { 1462 | "forwarded": "0.1.2", 1463 | "ipaddr.js": "1.6.0" 1464 | } 1465 | }, 1466 | "pseudomap": { 1467 | "version": "1.0.2", 1468 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 1469 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" 1470 | }, 1471 | "punycode": { 1472 | "version": "1.4.1", 1473 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1474 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 1475 | }, 1476 | "qs": { 1477 | "version": "6.5.2", 1478 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 1479 | "integrity": 1480 | "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 1481 | }, 1482 | "range-parser": { 1483 | "version": "1.2.0", 1484 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 1485 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 1486 | }, 1487 | "raw-body": { 1488 | "version": "2.3.3", 1489 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", 1490 | "integrity": 1491 | "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", 1492 | "requires": { 1493 | "bytes": "3.0.0", 1494 | "http-errors": "1.6.3", 1495 | "iconv-lite": "0.4.23", 1496 | "unpipe": "1.0.0" 1497 | } 1498 | }, 1499 | "read-pkg": { 1500 | "version": "2.0.0", 1501 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", 1502 | "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", 1503 | "requires": { 1504 | "load-json-file": "2.0.0", 1505 | "normalize-package-data": "2.4.0", 1506 | "path-type": "2.0.0" 1507 | } 1508 | }, 1509 | "read-pkg-up": { 1510 | "version": "2.0.0", 1511 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", 1512 | "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", 1513 | "requires": { 1514 | "find-up": "2.1.0", 1515 | "read-pkg": "2.0.0" 1516 | } 1517 | }, 1518 | "readable-stream": { 1519 | "version": "2.3.5", 1520 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", 1521 | "integrity": 1522 | "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", 1523 | "requires": { 1524 | "core-util-is": "1.0.2", 1525 | "inherits": "2.0.3", 1526 | "isarray": "1.0.0", 1527 | "process-nextick-args": "2.0.0", 1528 | "safe-buffer": "5.1.2", 1529 | "string_decoder": "1.0.3", 1530 | "util-deprecate": "1.0.2" 1531 | } 1532 | }, 1533 | "redeyed": { 1534 | "version": "1.0.1", 1535 | "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-1.0.1.tgz", 1536 | "integrity": "sha1-6WwZO0DAgWsArshCaY5hGF5VSYo=", 1537 | "requires": { 1538 | "esprima": "3.0.0" 1539 | } 1540 | }, 1541 | "regenerator-runtime": { 1542 | "version": "0.11.1", 1543 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", 1544 | "integrity": 1545 | "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" 1546 | }, 1547 | "request": { 1548 | "version": "2.87.0", 1549 | "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", 1550 | "integrity": 1551 | "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", 1552 | "requires": { 1553 | "aws-sign2": "0.7.0", 1554 | "aws4": "1.7.0", 1555 | "caseless": "0.12.0", 1556 | "combined-stream": "1.0.6", 1557 | "extend": "3.0.1", 1558 | "forever-agent": "0.6.1", 1559 | "form-data": "2.3.2", 1560 | "har-validator": "5.0.3", 1561 | "http-signature": "1.2.0", 1562 | "is-typedarray": "1.0.0", 1563 | "isstream": "0.1.2", 1564 | "json-stringify-safe": "5.0.1", 1565 | "mime-types": "2.1.18", 1566 | "oauth-sign": "0.8.2", 1567 | "performance-now": "2.1.0", 1568 | "qs": "6.5.2", 1569 | "safe-buffer": "5.1.2", 1570 | "tough-cookie": "2.3.4", 1571 | "tunnel-agent": "0.6.0", 1572 | "uuid": "3.2.1" 1573 | } 1574 | }, 1575 | "request-promise": { 1576 | "version": "4.2.2", 1577 | "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz", 1578 | "integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=", 1579 | "requires": { 1580 | "bluebird": "3.5.1", 1581 | "request-promise-core": "1.1.1", 1582 | "stealthy-require": "1.1.1", 1583 | "tough-cookie": "2.3.4" 1584 | } 1585 | }, 1586 | "request-promise-core": { 1587 | "version": "1.1.1", 1588 | "resolved": 1589 | "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", 1590 | "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", 1591 | "requires": { 1592 | "lodash": "4.17.10" 1593 | } 1594 | }, 1595 | "require-directory": { 1596 | "version": "2.1.1", 1597 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1598 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" 1599 | }, 1600 | "require-main-filename": { 1601 | "version": "1.0.1", 1602 | "resolved": 1603 | "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", 1604 | "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" 1605 | }, 1606 | "resolve": { 1607 | "version": "1.7.1", 1608 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", 1609 | "integrity": 1610 | "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", 1611 | "requires": { 1612 | "path-parse": "1.0.5" 1613 | } 1614 | }, 1615 | "retry-as-promised": { 1616 | "version": "2.3.2", 1617 | "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-2.3.2.tgz", 1618 | "integrity": "sha1-zZdO5P2bX+A8vzGHHuSCIcB3N7c=", 1619 | "requires": { 1620 | "bluebird": "3.5.1", 1621 | "debug": "2.6.9" 1622 | } 1623 | }, 1624 | "safe-buffer": { 1625 | "version": "5.1.2", 1626 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1627 | "integrity": 1628 | "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1629 | }, 1630 | "safer-buffer": { 1631 | "version": "2.1.2", 1632 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1633 | "integrity": 1634 | "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1635 | }, 1636 | "sax": { 1637 | "version": "1.2.4", 1638 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 1639 | "integrity": 1640 | "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" 1641 | }, 1642 | "semver": { 1643 | "version": "5.5.0", 1644 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", 1645 | "integrity": 1646 | "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" 1647 | }, 1648 | "send": { 1649 | "version": "0.16.2", 1650 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", 1651 | "integrity": 1652 | "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", 1653 | "requires": { 1654 | "debug": "2.6.9", 1655 | "depd": "1.1.2", 1656 | "destroy": "1.0.4", 1657 | "encodeurl": "1.0.2", 1658 | "escape-html": "1.0.3", 1659 | "etag": "1.8.1", 1660 | "fresh": "0.5.2", 1661 | "http-errors": "1.6.3", 1662 | "mime": "1.4.1", 1663 | "ms": "2.0.0", 1664 | "on-finished": "2.3.0", 1665 | "range-parser": "1.2.0", 1666 | "statuses": "1.4.0" 1667 | }, 1668 | "dependencies": { 1669 | "statuses": { 1670 | "version": "1.4.0", 1671 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 1672 | "integrity": 1673 | "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 1674 | } 1675 | } 1676 | }, 1677 | "seq-queue": { 1678 | "version": "0.0.5", 1679 | "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", 1680 | "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" 1681 | }, 1682 | "sequelize": { 1683 | "version": "4.37.10", 1684 | "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-4.37.10.tgz", 1685 | "integrity": 1686 | "sha512-Ugfqfciorsq2xX2xOimp/f2VVQdMAnClrl+0i34OgjVgQOAXDjgbbA5TwYTgGNxuv/a7r3+ELQi28mNmoizsSw==", 1687 | "requires": { 1688 | "bluebird": "3.5.1", 1689 | "cls-bluebird": "2.1.0", 1690 | "debug": "3.1.0", 1691 | "depd": "1.1.2", 1692 | "dottie": "2.0.0", 1693 | "generic-pool": "3.4.2", 1694 | "inflection": "1.12.0", 1695 | "lodash": "4.17.10", 1696 | "moment": "2.22.1", 1697 | "moment-timezone": "0.5.17", 1698 | "retry-as-promised": "2.3.2", 1699 | "semver": "5.5.0", 1700 | "terraformer-wkt-parser": "1.2.0", 1701 | "toposort-class": "1.0.1", 1702 | "uuid": "3.2.1", 1703 | "validator": "9.4.1", 1704 | "wkx": "0.4.5" 1705 | }, 1706 | "dependencies": { 1707 | "debug": { 1708 | "version": "3.1.0", 1709 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 1710 | "integrity": 1711 | "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 1712 | "requires": { 1713 | "ms": "2.0.0" 1714 | } 1715 | } 1716 | } 1717 | }, 1718 | "sequelize-cli": { 1719 | "version": "4.0.0", 1720 | "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-4.0.0.tgz", 1721 | "integrity": "sha1-TWQd+1iwNwq0QPc34bC/c38V7KU=", 1722 | "requires": { 1723 | "bluebird": "3.5.1", 1724 | "cli-color": "1.2.0", 1725 | "fs-extra": "5.0.0", 1726 | "js-beautify": "1.7.5", 1727 | "lodash": "4.17.10", 1728 | "resolve": "1.7.1", 1729 | "umzug": "2.1.0", 1730 | "yargs": "8.0.2" 1731 | } 1732 | }, 1733 | "serve-static": { 1734 | "version": "1.13.2", 1735 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", 1736 | "integrity": 1737 | "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", 1738 | "requires": { 1739 | "encodeurl": "1.0.2", 1740 | "escape-html": "1.0.3", 1741 | "parseurl": "1.3.2", 1742 | "send": "0.16.2" 1743 | } 1744 | }, 1745 | "set-blocking": { 1746 | "version": "2.0.0", 1747 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1748 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" 1749 | }, 1750 | "setprototypeof": { 1751 | "version": "1.1.0", 1752 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 1753 | "integrity": 1754 | "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 1755 | }, 1756 | "shebang-command": { 1757 | "version": "1.2.0", 1758 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 1759 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 1760 | "requires": { 1761 | "shebang-regex": "1.0.0" 1762 | } 1763 | }, 1764 | "shebang-regex": { 1765 | "version": "1.0.0", 1766 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 1767 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" 1768 | }, 1769 | "shimmer": { 1770 | "version": "1.2.0", 1771 | "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.0.tgz", 1772 | "integrity": 1773 | "sha512-xTCx2vohXC2EWWDqY/zb4+5Mu28D+HYNSOuFzsyRDRvI/e1ICb69afwaUwfjr+25ZXldbOLyp+iDUZHq8UnTag==" 1774 | }, 1775 | "sigmund": { 1776 | "version": "1.0.1", 1777 | "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", 1778 | "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" 1779 | }, 1780 | "signal-exit": { 1781 | "version": "3.0.2", 1782 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1783 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 1784 | }, 1785 | "spdx-correct": { 1786 | "version": "3.0.0", 1787 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", 1788 | "integrity": 1789 | "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", 1790 | "requires": { 1791 | "spdx-expression-parse": "3.0.0", 1792 | "spdx-license-ids": "3.0.0" 1793 | } 1794 | }, 1795 | "spdx-exceptions": { 1796 | "version": "2.1.0", 1797 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", 1798 | "integrity": 1799 | "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" 1800 | }, 1801 | "spdx-expression-parse": { 1802 | "version": "3.0.0", 1803 | "resolved": 1804 | "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", 1805 | "integrity": 1806 | "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", 1807 | "requires": { 1808 | "spdx-exceptions": "2.1.0", 1809 | "spdx-license-ids": "3.0.0" 1810 | } 1811 | }, 1812 | "spdx-license-ids": { 1813 | "version": "3.0.0", 1814 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", 1815 | "integrity": 1816 | "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" 1817 | }, 1818 | "sqlstring": { 1819 | "version": "2.3.1", 1820 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", 1821 | "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" 1822 | }, 1823 | "sshpk": { 1824 | "version": "1.14.1", 1825 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", 1826 | "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", 1827 | "requires": { 1828 | "asn1": "0.2.3", 1829 | "assert-plus": "1.0.0", 1830 | "bcrypt-pbkdf": "1.0.1", 1831 | "dashdash": "1.14.1", 1832 | "ecc-jsbn": "0.1.1", 1833 | "getpass": "0.1.7", 1834 | "jsbn": "0.1.1", 1835 | "tweetnacl": "0.14.5" 1836 | } 1837 | }, 1838 | "statuses": { 1839 | "version": "1.5.0", 1840 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1841 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 1842 | }, 1843 | "stealthy-require": { 1844 | "version": "1.1.1", 1845 | "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", 1846 | "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" 1847 | }, 1848 | "string-width": { 1849 | "version": "2.1.1", 1850 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1851 | "integrity": 1852 | "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1853 | "requires": { 1854 | "is-fullwidth-code-point": "2.0.0", 1855 | "strip-ansi": "4.0.0" 1856 | }, 1857 | "dependencies": { 1858 | "ansi-regex": { 1859 | "version": "3.0.0", 1860 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 1861 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" 1862 | }, 1863 | "is-fullwidth-code-point": { 1864 | "version": "2.0.0", 1865 | "resolved": 1866 | "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 1867 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" 1868 | }, 1869 | "strip-ansi": { 1870 | "version": "4.0.0", 1871 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1872 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1873 | "requires": { 1874 | "ansi-regex": "3.0.0" 1875 | } 1876 | } 1877 | } 1878 | }, 1879 | "string_decoder": { 1880 | "version": "1.0.3", 1881 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 1882 | "integrity": 1883 | "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 1884 | "requires": { 1885 | "safe-buffer": "5.1.2" 1886 | } 1887 | }, 1888 | "strip-ansi": { 1889 | "version": "3.0.1", 1890 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1891 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1892 | "requires": { 1893 | "ansi-regex": "2.1.1" 1894 | } 1895 | }, 1896 | "strip-bom": { 1897 | "version": "3.0.0", 1898 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 1899 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" 1900 | }, 1901 | "strip-eof": { 1902 | "version": "1.0.0", 1903 | "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", 1904 | "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" 1905 | }, 1906 | "strip-indent": { 1907 | "version": "2.0.0", 1908 | "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", 1909 | "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", 1910 | "dev": true 1911 | }, 1912 | "supports-color": { 1913 | "version": "5.4.0", 1914 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", 1915 | "integrity": 1916 | "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", 1917 | "dev": true, 1918 | "requires": { 1919 | "has-flag": "3.0.0" 1920 | } 1921 | }, 1922 | "terraformer": { 1923 | "version": "1.0.8", 1924 | "resolved": "https://registry.npmjs.org/terraformer/-/terraformer-1.0.8.tgz", 1925 | "integrity": "sha1-UeCtiXRvzyFh3G9lqnDkI3fItZM=", 1926 | "requires": { 1927 | "@types/geojson": "1.0.6" 1928 | } 1929 | }, 1930 | "terraformer-wkt-parser": { 1931 | "version": "1.2.0", 1932 | "resolved": 1933 | "https://registry.npmjs.org/terraformer-wkt-parser/-/terraformer-wkt-parser-1.2.0.tgz", 1934 | "integrity": 1935 | "sha512-QU3iA54St5lF8Za1jg1oj4NYc8sn5tCZ08aNSWDeGzrsaV48eZk1iAVWasxhNspYBoCqdHuoot1pUTUrE1AJ4w==", 1936 | "requires": { 1937 | "@types/geojson": "1.0.6", 1938 | "terraformer": "1.0.8" 1939 | } 1940 | }, 1941 | "timers-ext": { 1942 | "version": "0.1.5", 1943 | "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.5.tgz", 1944 | "integrity": 1945 | "sha512-tsEStd7kmACHENhsUPaxb8Jf8/+GZZxyNFQbZD07HQOyooOa6At1rQqjffgvg7n+dxscQa9cjjMdWhJtsP2sxg==", 1946 | "requires": { 1947 | "es5-ext": "0.10.45", 1948 | "next-tick": "1.0.0" 1949 | } 1950 | }, 1951 | "toposort-class": { 1952 | "version": "1.0.1", 1953 | "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", 1954 | "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" 1955 | }, 1956 | "tough-cookie": { 1957 | "version": "2.3.4", 1958 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", 1959 | "integrity": 1960 | "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", 1961 | "requires": { 1962 | "punycode": "1.4.1" 1963 | } 1964 | }, 1965 | "tunnel-agent": { 1966 | "version": "0.6.0", 1967 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1968 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1969 | "requires": { 1970 | "safe-buffer": "5.1.2" 1971 | } 1972 | }, 1973 | "tweetnacl": { 1974 | "version": "0.14.5", 1975 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1976 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 1977 | "optional": true 1978 | }, 1979 | "type-is": { 1980 | "version": "1.6.16", 1981 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", 1982 | "integrity": 1983 | "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", 1984 | "requires": { 1985 | "media-typer": "0.3.0", 1986 | "mime-types": "2.1.18" 1987 | } 1988 | }, 1989 | "umzug": { 1990 | "version": "2.1.0", 1991 | "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.1.0.tgz", 1992 | "integrity": 1993 | "sha512-BgT+ekpItEWaG+3JjLLj6yVTxw2wIH8Cr6JyKYIzukWAx9nzGhC6BGHb/IRMjpobMM1qtIrReATwLUjKpU2iOQ==", 1994 | "requires": { 1995 | "babel-runtime": "6.26.0", 1996 | "bluebird": "3.5.1", 1997 | "lodash": "4.17.10", 1998 | "resolve": "1.7.1" 1999 | } 2000 | }, 2001 | "universalify": { 2002 | "version": "0.1.1", 2003 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", 2004 | "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" 2005 | }, 2006 | "unpipe": { 2007 | "version": "1.0.0", 2008 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 2009 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 2010 | }, 2011 | "util-deprecate": { 2012 | "version": "1.0.2", 2013 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2014 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 2015 | }, 2016 | "utils-merge": { 2017 | "version": "1.0.1", 2018 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 2019 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 2020 | }, 2021 | "uuid": { 2022 | "version": "3.2.1", 2023 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", 2024 | "integrity": 2025 | "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" 2026 | }, 2027 | "validate-npm-package-license": { 2028 | "version": "3.0.3", 2029 | "resolved": 2030 | "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", 2031 | "integrity": 2032 | "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", 2033 | "requires": { 2034 | "spdx-correct": "3.0.0", 2035 | "spdx-expression-parse": "3.0.0" 2036 | } 2037 | }, 2038 | "validator": { 2039 | "version": "9.4.1", 2040 | "resolved": "https://registry.npmjs.org/validator/-/validator-9.4.1.tgz", 2041 | "integrity": 2042 | "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==" 2043 | }, 2044 | "vary": { 2045 | "version": "1.1.2", 2046 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 2047 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 2048 | }, 2049 | "verror": { 2050 | "version": "1.10.0", 2051 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 2052 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 2053 | "requires": { 2054 | "assert-plus": "1.0.0", 2055 | "core-util-is": "1.0.2", 2056 | "extsprintf": "1.3.0" 2057 | } 2058 | }, 2059 | "which": { 2060 | "version": "1.3.1", 2061 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 2062 | "integrity": 2063 | "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 2064 | "requires": { 2065 | "isexe": "2.0.0" 2066 | } 2067 | }, 2068 | "which-module": { 2069 | "version": "2.0.0", 2070 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 2071 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" 2072 | }, 2073 | "wkx": { 2074 | "version": "0.4.5", 2075 | "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.5.tgz", 2076 | "integrity": 2077 | "sha512-01dloEcJZAJabLO5XdcRgqdKpmnxS0zIT02LhkdWOZX2Zs2tPM6hlZ4XG9tWaWur1Qd1OO4kJxUbe2+5BofvnA==", 2078 | "requires": { 2079 | "@types/node": "10.1.3" 2080 | } 2081 | }, 2082 | "wrap-ansi": { 2083 | "version": "2.1.0", 2084 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", 2085 | "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", 2086 | "requires": { 2087 | "string-width": "1.0.2", 2088 | "strip-ansi": "3.0.1" 2089 | }, 2090 | "dependencies": { 2091 | "string-width": { 2092 | "version": "1.0.2", 2093 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 2094 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 2095 | "requires": { 2096 | "code-point-at": "1.1.0", 2097 | "is-fullwidth-code-point": "1.0.0", 2098 | "strip-ansi": "3.0.1" 2099 | } 2100 | } 2101 | } 2102 | }, 2103 | "xml": { 2104 | "version": "1.0.1", 2105 | "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", 2106 | "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=" 2107 | }, 2108 | "xml2js": { 2109 | "version": "0.4.19", 2110 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", 2111 | "integrity": 2112 | "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", 2113 | "requires": { 2114 | "sax": "1.2.4", 2115 | "xmlbuilder": "9.0.7" 2116 | } 2117 | }, 2118 | "xmlbuilder": { 2119 | "version": "9.0.7", 2120 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", 2121 | "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" 2122 | }, 2123 | "y18n": { 2124 | "version": "3.2.1", 2125 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", 2126 | "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" 2127 | }, 2128 | "yallist": { 2129 | "version": "2.1.2", 2130 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 2131 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" 2132 | }, 2133 | "yargs": { 2134 | "version": "8.0.2", 2135 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", 2136 | "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", 2137 | "requires": { 2138 | "camelcase": "4.1.0", 2139 | "cliui": "3.2.0", 2140 | "decamelize": "1.2.0", 2141 | "get-caller-file": "1.0.2", 2142 | "os-locale": "2.1.0", 2143 | "read-pkg-up": "2.0.0", 2144 | "require-directory": "2.1.1", 2145 | "require-main-filename": "1.0.1", 2146 | "set-blocking": "2.0.0", 2147 | "string-width": "2.1.1", 2148 | "which-module": "2.0.0", 2149 | "y18n": "3.2.1", 2150 | "yargs-parser": "7.0.0" 2151 | } 2152 | }, 2153 | "yargs-parser": { 2154 | "version": "7.0.0", 2155 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", 2156 | "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", 2157 | "requires": { 2158 | "camelcase": "4.1.0" 2159 | } 2160 | } 2161 | } 2162 | } 2163 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "garoogle", 3 | "version": "1.1.1", 4 | "description": "GaroonからGoogle Calendarへ予定を更新します", 5 | "scripts": { 6 | "start": "node src/index.js", 7 | "start:batch": "node src/batch.js", 8 | "migrate": "sequelize db:migrate", 9 | "fmt": "prettier --write **/*.{js,json,md}", 10 | "precommit": "pretty-quick --staged" 11 | }, 12 | "author": "hiroppy (https://hiroppy.me)", 13 | "license": "MIT", 14 | "dependencies": { 15 | "@about_hiroppy/node-google-calendar": "^1.1.2", 16 | "body-parser": "^1.18.3", 17 | "cron": "^1.3.0", 18 | "express": "^4.16.3", 19 | "garoon-soap": "^0.1.9", 20 | "lodash.xor": "^4.5.0", 21 | "mysql2": "^1.5.3", 22 | "sequelize": "^4.37.10", 23 | "sequelize-cli": "^4.0.0" 24 | }, 25 | "devDependencies": { 26 | "husky": "^0.14.3", 27 | "prettier": "^1.13.4", 28 | "pretty-quick": "^1.6.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /sequelize/cli.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const config = { 4 | username: process.env.MYSQL_USER, 5 | password: process.env.MYSQL_ROOT_PASSWORD, 6 | database: process.env.MYSQL_DATABASE, 7 | host: 'mysql', 8 | dialect: 'mysql' 9 | }; 10 | 11 | module.exports = { 12 | development: config, 13 | test: config, 14 | production: config 15 | }; 16 | -------------------------------------------------------------------------------- /sequelize/migrations/20180610013241-meta.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | up: (queryInterface, Sequelize) => { 5 | return queryInterface.createTable('meta', { 6 | latestEventsList: Sequelize.TEXT, 7 | nextSyncToken: Sequelize.STRING, 8 | resourceId: Sequelize.STRING, 9 | currentChannelId: Sequelize.STRING 10 | }); 11 | }, 12 | 13 | down: (queryInterface, Sequelize) => { 14 | return queryInterface.dropTable('meta'); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /sequelize/migrations/20180610013915-events.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | up: (queryInterface, Sequelize) => { 5 | return queryInterface.createTable( 6 | 'events', 7 | { 8 | garoonId: Sequelize.STRING, 9 | googleId: Sequelize.STRING, 10 | startTime: Sequelize.STRING, 11 | endTime: Sequelize.STRING, 12 | summary: Sequelize.STRING, 13 | description: Sequelize.TEXT, 14 | private: Sequelize.BOOLEAN, 15 | members: Sequelize.TEXT 16 | }, 17 | { 18 | charset: 'utf8' 19 | } 20 | ); 21 | }, 22 | 23 | down: (queryInterface, Sequelize) => { 24 | return queryInterface.dropTable('events'); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /sequelize/migrations/20180610014533-events.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | up: (queryInterface, Sequelize) => { 5 | return queryInterface.addColumn('events', 'place', { type: Sequelize.STRING }); 6 | }, 7 | 8 | down: (queryInterface, Sequelize) => { 9 | return queryInterface.removeColumn('event', 'place'); 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /src/batch.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { randomBytes } = require('crypto'); 4 | const { CronJob } = require('cron'); 5 | const { watch, stopChannel } = require('./google-calendar'); 6 | const { getMeta, setMeta } = require('./store'); 7 | 8 | if (process.env.CALLBACK_URL === undefined) process.exit(); 9 | 10 | new CronJob( 11 | '0 0 0 * * *', 12 | async () => { 13 | await startTasks(); 14 | }, 15 | null, 16 | true 17 | ); 18 | 19 | startTasks(); 20 | 21 | async function startTasks() { 22 | const channelId = randomBytes(10).toString('hex'); 23 | 24 | try { 25 | const { id, resourceId } = await watch(channelId); 26 | const meta = await getMeta(); 27 | 28 | await setMeta( 29 | { 30 | resourceId, 31 | currentChannelId: id 32 | }, 33 | meta === null ? 'create' : 'update' 34 | ); 35 | 36 | // await stopChannel(); 37 | // require('./google-calendar').stopChannel( 38 | // req.headers['x-goog-channel-id'], 39 | // req.headers['x-goog-resource-id'] 40 | // ); 41 | } catch (e) { 42 | console.error(e); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/garoon.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const GaroonSoap = require('garoon-soap'); 4 | 5 | const garoon = new GaroonSoap( 6 | process.env.GAROON_URL, 7 | process.env.GAROON_MY_NAME, 8 | process.env.GAROON_MY_PASSWORD 9 | ); 10 | const ignoredPlans = process.env.PLAN_FILTER.split(',').map((s) => s.trim()); 11 | 12 | async function getEvents() { 13 | const start = new Date(); 14 | const end = new Date(); 15 | 16 | end.setDate(start.getDate() + (Number(process.env.TERM) || 30)); 17 | 18 | const res = await garoon.schedule.getEvents(start, end); 19 | 20 | if (res == undefined) return null; 21 | return res.filter((e) => !ignoredPlans.includes(e.plan)); 22 | } 23 | 24 | async function addEvents(arr) { 25 | return garoon.schedule.addEvents(arr); 26 | } 27 | 28 | /* 29 | { id: '4226798', 30 | eventType: 'normal', 31 | version: '1527403075', 32 | publicType: 'private', 33 | plan: '外出', 34 | detail: 'Title', 35 | description: undefined, 36 | timezone: 'Asia/Tokyo', 37 | endTimezone: 'Asia/Tokyo', 38 | allday: false, 39 | startOnly: false, 40 | members: { users: [Array], organizations: [], facilities: [] }, 41 | observers: { users: [], organizations: [], roles: [] }, 42 | when: { datetimes: [Array], dates: [] }, 43 | follows: [], 44 | files: [], 45 | removeFileIds: [] }, 46 | */ 47 | async function modifyEvents(arr) { 48 | return garoon.schedule.modifyEvents(arr); 49 | } 50 | 51 | async function deleteEvents(arr) { 52 | return garoon.schedule.removeEvents(arr); 53 | } 54 | 55 | async function getFacilities(ids) { 56 | const places = await garoon.schedule.getFacilitiesById(ids); 57 | 58 | if (places.length) return ''; 59 | 60 | return places[0].name; 61 | // return places.map((e) => e.name); 62 | } 63 | 64 | function formatSchema(event) { 65 | const { when, plan, publicType, description, members } = event; 66 | let startTime, endTime, place; 67 | 68 | // TODO: wip 69 | if (event.eventType === 'repeat') { 70 | } 71 | 72 | if (when === undefined) return null; 73 | 74 | // TODO: なんで配列なのか調べてないので、とりあえず0番目だけ 75 | if (when.dates.length !== 0) { 76 | // 一日以上の予定 77 | startTime = when.dates[0].start; 78 | endTime = when.dates[0].end; 79 | } else if (when.datetimes.length !== 0) { 80 | // 時間指定された予定 81 | startTime = when.datetimes[0].start; 82 | endTime = when.datetimes[0].end; 83 | } 84 | 85 | // place 86 | // TODO: とりあえず一番プライオリティが高い0番目のみ 87 | if (Array.isArray(members.facilities)) { 88 | const placeInfo = members.facilities[0]; 89 | 90 | if (placeInfo) place = placeInfo.id; 91 | } 92 | 93 | const summary = `${event.plan ? `${event.plan}: ${event.detail}` : event.detail}`.trim(); 94 | 95 | return { 96 | summary, 97 | place, 98 | description, 99 | startTime: new Date(startTime).getTime(), 100 | endTime: new Date(endTime).getTime(), 101 | members: JSON.stringify(event.members), 102 | private: publicType === 'private' 103 | }; 104 | } 105 | 106 | module.exports = { 107 | getEvents, 108 | addEvents, 109 | modifyEvents, 110 | deleteEvents, 111 | getFacilities, 112 | formatSchema 113 | }; 114 | -------------------------------------------------------------------------------- /src/google-calendar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { resolve } = require('path'); 4 | const { addEvents, modifyEvents, deleteEvents } = require('./garoon'); 5 | const CalendarAPI = require('@about_hiroppy/node-google-calendar'); 6 | const { 7 | getMeta, 8 | setMeta, 9 | setEvent, 10 | getEvent, 11 | updateEvent: updateDBEvent, 12 | deleteEvent: deleteDBEvent 13 | } = require('./store'); 14 | const { private_key: key } = require(resolve(process.env.GOOGLE_API_KEY_FILE)); 15 | 16 | if (!key) { 17 | console.error('private key is empty'); 18 | process.exit(1); 19 | } 20 | 21 | const calendarId = process.env.CALENDAR_ID; 22 | const cal = new CalendarAPI({ 23 | key, 24 | timezone: 'UTC+09:00', 25 | calendarId: { 26 | garoon: process.env.CALENDAR_ID 27 | }, 28 | serviceAcctId: process.env.SERVICE_ACCT_ID 29 | }); 30 | 31 | function createParams({ 32 | private: isPrivate, 33 | startTime, 34 | endTime, 35 | summary, 36 | description, 37 | place: location 38 | }) { 39 | return { 40 | start: { dateTime: new Date(startTime) }, 41 | end: { dateTime: new Date(endTime) }, 42 | visibility: isPrivate ? 'private' : undefined, 43 | summary, 44 | location, 45 | description 46 | }; 47 | } 48 | 49 | /** 50 | * 予定のメンバーが複数人のときに、操作を許可するかどうか 51 | * SATEFYがtrueのときは、更新と削除はGoogle CalendarからGaroonへの変更は行わない 52 | */ 53 | function isAllow(data) { 54 | if (!Reflect.has(data, 'members')) return false; 55 | if (!process.env.SAFETY) return true; 56 | 57 | const { users } = JSON.parse(data.members); 58 | 59 | return users && users.length === 1 && users[0].id === process.env.GAROON_MY_ID; 60 | } 61 | 62 | /** 63 | * Google Calendarからwebhookを受けたときの処理(server.jsからemitされる) 64 | * `sync`と`exist`は同じ処理を行う 65 | */ 66 | async function refreshList(ee) { 67 | ee.on('onFetchList', async (headers) => { 68 | const meta = await getMeta(); 69 | 70 | if (meta === null) return; 71 | 72 | const { nextSyncToken: syncToken, currentChannelId } = meta; 73 | 74 | if (headers.channelId !== currentChannelId) return; 75 | 76 | const { items, nextSyncToken } = await getList({ syncToken }); 77 | 78 | // syncTokenが空の場合は処理を行わず、最後DBへの挿入のみとする 79 | if (syncToken !== null) { 80 | for (let i = 0; i < items.length; i++) { 81 | const { id: googleId, status, start, end, summary, description, visibility } = items[i]; 82 | const data = await getEvent({ googleId }); 83 | 84 | // 削除 85 | if (status === 'cancelled') { 86 | if (data && isAllow(data)) { 87 | try { 88 | await deleteEvents([data.garoonId]); 89 | await deleteDBEvent(data.id); 90 | } catch (e) { 91 | console.error(e); 92 | } 93 | } 94 | continue; 95 | } 96 | 97 | // DBスキーマ 98 | const schema = { 99 | summary, 100 | description, 101 | private: visibility === 'private', 102 | startTime: new Date(start.dateTime).getTime().toString(), 103 | endTime: new Date(end.dateTime).getTime().toString() 104 | }; 105 | 106 | // Garoonへの投稿スキーマのベース 107 | const postedSchema = { 108 | detail: schema.summary, 109 | description: schema.description, 110 | publicType: schema.private ? 'private' : 'public', 111 | when: { 112 | datetimes: [ 113 | { 114 | start: new Date(start.dateTime), 115 | end: new Date(end.dateTime) 116 | } 117 | ], 118 | dates: [] 119 | } 120 | }; 121 | 122 | // DBに存在しなければ、新規予定なので、DBへ追加しGaroonへ投稿 123 | if (data == null) { 124 | try { 125 | const [{ id: garoonId, members }] = await addEvents([ 126 | { 127 | ...postedSchema, 128 | members: { 129 | users: [ 130 | { 131 | id: process.env.GAROON_MY_ID 132 | } 133 | ], 134 | organizations: [], 135 | facilities: [] 136 | } 137 | } 138 | ]); 139 | 140 | await setEvent({ 141 | ...schema, 142 | garoonId, 143 | googleId, 144 | members: JSON.stringify(members) 145 | }); 146 | } catch (e) { 147 | console.error(e); 148 | } 149 | } 150 | 151 | // 存在すれば、以前から更新があるかの確認をし、上書きする 152 | // locationは使わない(garoon -> google calendarのみの適用) 153 | if (data && isAllow(data) && isUpdatedEvent(schema, data)) { 154 | try { 155 | await modifyEvents([ 156 | { 157 | ...postedSchema, 158 | id: data.garoonId, 159 | members: JSON.parse(data.members) 160 | } 161 | ]); 162 | await updateDBEvent(schema, data.id); 163 | } catch (e) { 164 | console.error(e); 165 | } 166 | } 167 | } 168 | } 169 | 170 | await setMeta({ nextSyncToken }); 171 | }); 172 | } 173 | 174 | async function getList(obj = {}) { 175 | return cal.Events.list(calendarId, obj); 176 | } 177 | 178 | async function postEvent(obj) { 179 | const params = createParams(obj); 180 | 181 | return cal.Events.insert(calendarId, params); 182 | } 183 | 184 | async function updateEvent(eventId, obj) { 185 | const params = createParams(obj); 186 | 187 | return cal.Events.update(calendarId, eventId, params); 188 | } 189 | 190 | async function deleteEvent(eventId) { 191 | return cal.Events.delete(calendarId, eventId, {}); 192 | } 193 | 194 | async function watch(id) { 195 | return cal.Events.watch( 196 | calendarId, 197 | { 198 | id, 199 | type: 'web_hook', 200 | address: process.env.CALLBACK_URL 201 | // expiration: 1426325213000 202 | }, 203 | {} 204 | ); 205 | } 206 | 207 | async function stopChannel(id, resourceId) { 208 | return cal.Channels.stop({ 209 | id, 210 | resourceId 211 | }); 212 | } 213 | 214 | function isUpdatedEvent(e1, e2) { 215 | return ( 216 | e1.startTime.toString() !== e2.startTime.toString() || 217 | e1.endTime.toString() !== e2.endTime.toString() || 218 | e1.private !== e2.private || 219 | e1.summary != e2.summary || 220 | e1.place != e2.place || // google calendarからの変更は受け入れたくない 221 | e1.description != e2.description // null or undefined 222 | ); 223 | } 224 | 225 | module.exports = { 226 | getList, 227 | postEvent, 228 | updateEvent, 229 | deleteEvent, 230 | refreshList, 231 | watch, 232 | stopChannel, 233 | isUpdatedEvent 234 | }; 235 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // for Garoon 4 | process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0; 5 | 6 | // validate 7 | if ( 8 | !process.env.GAROON_URL || 9 | !process.env.GAROON_MY_ID || 10 | !process.env.GAROON_MY_NAME || 11 | !process.env.GAROON_MY_PASSWORD || 12 | !process.env.CALENDAR_ID || 13 | !process.env.SERVICE_ACCT_ID || 14 | !process.env.GOOGLE_API_KEY_FILE || 15 | !process.env.MYSQL_ROOT_PASSWORD || 16 | !process.env.MYSQL_DATABASE || 17 | !process.env.MYSQL_USER || 18 | !process.env.MYSQL_PASSWORD 19 | ) { 20 | console.error('引数が足りません。'); 21 | process.exit(1); 22 | } 23 | 24 | const { EventEmitter } = require('events'); 25 | const { CronJob } = require('cron'); 26 | const xor = require('lodash.xor'); 27 | const { getEvents, getFacilities, formatSchema } = require('./garoon'); 28 | const { init: initServer, updateLastUpdated } = require('./server'); 29 | const { 30 | postEvent, 31 | updateEvent, 32 | deleteEvent, 33 | refreshList, 34 | isUpdatedEvent 35 | } = require('./google-calendar'); 36 | const { 37 | setEvent, 38 | getEvent, 39 | updateEvent: updateDBEvent, 40 | deleteEvent: destroyEvent, 41 | getMeta, 42 | setMeta 43 | } = require('./store'); 44 | 45 | const ee = new EventEmitter(); 46 | 47 | initServer(ee); 48 | 49 | // Google Calendarからのwebhookを受け取ったときの処理 50 | if (process.env.CALLBACK_URL) refreshList(ee); 51 | 52 | new CronJob( 53 | process.env.CRON, 54 | async () => { 55 | await run(); 56 | }, 57 | null, 58 | true 59 | ); 60 | 61 | run(); 62 | 63 | async function run() { 64 | console.log(`${new Date()} fetching...`); 65 | 66 | const res = await getEvents(); 67 | const idList = []; 68 | 69 | for (let i = 0; i < res.length; i++) { 70 | const event = res[i]; 71 | const schema = formatSchema(event); 72 | 73 | if (schema === null) continue; 74 | 75 | const { id: garoonId } = event; 76 | const item = await getEvent({ garoonId }); 77 | 78 | idList.push(garoonId); 79 | 80 | if (item === null) { 81 | // insert 82 | const place = schema.place ? await getFacilities([schema.place]) : undefined; 83 | 84 | // DBには場所のIDしかいれたくないため、schema.placeの上書きはしない。 85 | const { id: googleId } = await postEvent({ 86 | ...schema, 87 | place 88 | }); 89 | 90 | await setEvent({ 91 | ...schema, 92 | googleId, 93 | garoonId 94 | }); 95 | } else { 96 | // update 97 | if (isUpdatedEvent(item, schema)) { 98 | const { googleId, id } = item; 99 | const place = schema.place ? await getFacilities([schema.place]) : undefined; 100 | 101 | // DBには場所のIDしかいれたくないため、schema.placeの上書きはしない。 102 | await updateEvent(googleId, { 103 | ...schema, 104 | place 105 | }); 106 | await updateDBEvent(schema, id); 107 | } 108 | } 109 | } 110 | 111 | // 直前の取得したイベントのIDが入った配列 112 | const meta = await getMeta(); 113 | 114 | // 削除されたかどうかは一度処理を上で終わらせる必要がある(削除されたキーはforで回らないため) 115 | // 1. latestListにIDがないが、idListの中にあれば、追加された予定 (上記で処理が行われるため無視) 116 | // 2. latestListにIDがあるが、idListの中になければ、削除された予定 117 | if (meta) { 118 | const orphans = xor(JSON.parse(meta.latestEventsList), idList); 119 | 120 | for (let i = 0; i < orphans.length; i++) { 121 | const garoonId = orphans[i]; 122 | 123 | if (idList.includes(garoonId)) continue; 124 | 125 | // 2 126 | const item = await getEvent({ garoonId }); 127 | 128 | if (!item) continue; 129 | 130 | const { id, googleId, endTime } = item; 131 | 132 | if (endTime < new Date().getTime()) continue; 133 | 134 | try { 135 | await deleteEvent(googleId); 136 | } catch (e) { 137 | if (JSON.parse(e.message).error.statusCode !== '410(Gone)') throw e; 138 | } finally { 139 | await destroyEvent(id); 140 | } 141 | } 142 | } 143 | 144 | await setMeta({ latestEventsList: JSON.stringify(idList) }, meta === null ? 'create' : 'update'); 145 | updateLastUpdated(new Date().toLocaleString('ja', { timeZone: 'Asia/Tokyo' })); 146 | } 147 | 148 | process.on('unhandledRejection', (err) => { 149 | console.error(err); 150 | }); 151 | -------------------------------------------------------------------------------- /src/server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const express = require('express'); 4 | const bodyParser = require('body-parser'); 5 | 6 | let lastUpdated; 7 | 8 | function init(ee) { 9 | const app = express(); 10 | 11 | app.use(bodyParser()); 12 | 13 | app.get('/api/health', (req, res) => res.status(200).json({ lastUpdated })); 14 | app.post('/api/google/event', (req, res) => { 15 | const state = req.headers['x-goog-resource-state']; 16 | 17 | ee.emit('onFetchList', { 18 | channelId: req.headers['x-goog-channel-id'], 19 | resourceId: req.headers['x-goog-resource-id'] 20 | }); 21 | 22 | return res.status(200).send(':)'); 23 | }); 24 | 25 | app.listen(3000, () => { 26 | console.log('Started on PORT 3000'); 27 | }); 28 | } 29 | 30 | function updateLastUpdated(d) { 31 | lastUpdated = d; 32 | } 33 | 34 | module.exports = { 35 | init, 36 | updateLastUpdated 37 | }; 38 | -------------------------------------------------------------------------------- /src/store.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Sequelize = require('sequelize'); 4 | 5 | const sequelize = new Sequelize( 6 | process.env.MYSQL_DATABASE, 7 | process.env.MYSQL_USER, 8 | process.env.MYSQL_PASSWORD, 9 | { 10 | host: 'mysql', 11 | dialect: 'mysql', 12 | operatorsAliases: true, 13 | dialectOptions: { 14 | charset: 'utf8' 15 | }, 16 | logging: false 17 | } 18 | ); 19 | 20 | sequelize.sync(); 21 | 22 | const Meta = sequelize.define('meta', { 23 | latestEventsList: Sequelize.TEXT, 24 | nextSyncToken: Sequelize.STRING, 25 | resourceId: Sequelize.STRING, 26 | currentChannelId: Sequelize.STRING 27 | }); 28 | 29 | const Events = sequelize.define( 30 | 'events', 31 | { 32 | garoonId: Sequelize.STRING, 33 | googleId: Sequelize.STRING, 34 | startTime: Sequelize.STRING, 35 | endTime: Sequelize.STRING, 36 | summary: Sequelize.STRING, 37 | description: Sequelize.TEXT, 38 | private: Sequelize.BOOLEAN, 39 | members: Sequelize.TEXT, 40 | place: Sequelize.STRING 41 | }, 42 | { 43 | charset: 'utf8' 44 | } 45 | ); 46 | 47 | async function setEvent(q) { 48 | return Events.create(q); 49 | } 50 | 51 | async function getEvent(q) { 52 | const res = await Events.findOne({ where: q }); 53 | 54 | return res ? res.dataValues : null; 55 | } 56 | 57 | async function updateEvent(q, id) { 58 | const res = await Events.update(q, { where: { id } }); 59 | 60 | return res ? res.dataValues : null; 61 | } 62 | 63 | async function deleteEvent(id) { 64 | return Events.destroy({ where: { id } }); 65 | } 66 | 67 | async function setMeta(q, type = 'update') { 68 | if (type === 'update') { 69 | return Meta.update(q, { where: { id: 1 } }); 70 | } else if (type === 'create') { 71 | return Meta.create(q); 72 | } 73 | } 74 | 75 | async function getMeta() { 76 | const res = await Meta.findOne({ where: { id: 1 } }); 77 | 78 | return res ? res.dataValues : null; 79 | } 80 | 81 | module.exports = { 82 | setEvent, 83 | getEvent, 84 | updateEvent, 85 | deleteEvent, 86 | setMeta, 87 | getMeta 88 | }; 89 | --------------------------------------------------------------------------------