├── .editorconfig
├── .gitignore
├── LICENSE
├── README.md
├── accessibility.spec.js
├── budget
├── assert-metrics.spec.js
├── budget.json
└── helpers.js
├── cert-expiration.js
├── code-coverage.js
├── dark-mode.js
├── dom-snapshot.spec.js
├── element-to-pdf.js
├── fps.jpeg
├── fps.js
├── memory-leak-heap.spec.js
├── memory-leak-proto.spec.js
├── package-lock.json
├── package.json
├── pptrgram.js
├── pptrjourney.js
├── sample.jpg
├── security.js
├── side-by-side-pageload.js
├── speech.js
├── tensor-sample.jpg
├── tensorflow.html
├── tensorflow.js
├── timeline-trace.js
├── visual-regression.spec.js
└── whatsapp
├── .firebaserc
├── .gitignore
├── firebase.json
├── functions
├── .eslintrc.json
├── .gitignore
├── helpers.js
├── index.js
├── package-lock.json
└── package.json
├── storage.rules
└── whatsapp-demo.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | trim_trailing_whitespace = true
6 | insert_final_newline = true
7 | indent_style = space
8 | indent_size = 2
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | __snapshots__
3 | node_modules
4 | .idea
5 | coverage
6 | .nyc_output
7 | .screenshots
8 | pptgram/*
9 | whatsapp/.tmp
10 | dark.jpg
11 | light.jpg
12 | fps.jpg
13 | trace.json
14 | tweet.pdf
15 | tweet.png
16 | discord
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright 2018 Google Inc.
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Puppeteer Demos
2 |
3 | This repo contains various demos of the concepts, ideas and experiments over puppeteer that were demonstrated as part of the talks of mine. You can also find references of the links which are shown during the talk.
4 |
5 | 🎥 Video of the talk : https://www.youtube.com/watch?v=d2WSO3w5E94
6 |
7 | **Puppeteer can automate that! @HolyJS:** https://www.slideshare.net/nderCeylan/puppeteer-can-automate-that-holyjs-piter-2020
8 |
9 | **Puppeteer can automate that! @AmsterdamJS:** https://www.slideshare.net/nderCeylan/puppeteer-can-automate-that-amsterdamjs
10 |
11 | **Puppeteer can automate that! @Frontmania:** https://www.slideshare.net/nderCeylan/puppeteer-can-automate-that
12 |
13 | **Introducing perf budgets on CI with puppeteer @perf.now():** https://www.slideshare.net/nderCeylan/introducing-perf-budgets-on-ci-with-puppeteer
14 |
15 | > If you attended my talk, would you help me make my next one better? Please share your feedback with this form https://onderceylan.typeform.com/to/Z4SbFn. It'll only take a minute, promise :)
16 |
17 | The scripts in this repo are built for training and demonstration purposes, feel free to use them at your own risk.
18 |
19 | ## How to run scripts?
20 |
21 | Install dependencies
22 | ```
23 | npm i
24 | ```
25 |
26 | Execute scripts with
27 | ```
28 | node fps.js
29 | cd whatsapp && node whatsapp.js
30 | ```
31 |
32 | Run tests with
33 | ```
34 | npx jest dom-snapshot.spec.js
35 | cd budget && npx jest assert-metrics.spec.js
36 | ```
37 |
38 | ## References in talk
39 |
40 | * https://pptr.dev
41 | * https://try-puppeteer.appspot.com
42 | * https://github.com/transitive-bullshit/awesome-puppeteer
43 | * https://chrome.google.com/webstore/detail/puppeteer-recorder/djeegiggegleadkkbgopoonhjimgehda
44 | * https://github.com/ChromeDevTools/devtools-frontend
45 | * chrome://flags/#enable-devtools-experiments
46 | * chrome —-remote-debugging-port=9222
47 | * http://127.0.0.1:9222/devtools
48 | * http://127.0.0.1:9222/json/version
49 | * https://chromedevtools.github.io/devtools-protocol
50 | * https://github.com/ChromeDevTools/awesome-chrome-devtools
51 | * https://github.com/onderceylan/pwa-asset-generator
52 | * https://www.tensorflow.org/js/models
53 | * https://chromedevtools.github.io/timeline-viewer/
54 | * https://github.com/mapbox/pixelmatch#nodejs
55 | * https://github.com/serverless/examples/tree/master/aws-node-puppeteer
56 | * https://browserless.io
57 | * https://checklyhq.com
58 |
59 | ## Script references for some of the concepts
60 | * https://github.com/GoogleChromeLabs/puppeteer-examples
61 | * https://github.com/trentmwillis/devtools-protocol-demos
62 |
--------------------------------------------------------------------------------
/accessibility.spec.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 |
3 | // Inspiration: https://github.com/trentmwillis/devtools-protocol-demos/blob/master/testing-demos/accessibility.js
4 |
5 | beforeAll(async () => {
6 | this.browser = await puppeteer.launch();
7 | });
8 |
9 | afterAll(async () => {
10 | await this.browser.close();
11 | });
12 |
13 | test('app is accessible and has no accessibility violations', async() => {
14 | const page = await this.browser.newPage();
15 | await page.goto('https://frontmania.com');
16 |
17 | await page.addScriptTag({ url: 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/3.3.2/axe.min.js' });
18 | const results = await page.evaluate(() => axe.run(document));
19 |
20 | if (results.violations.length > 0) {
21 | console.log(`Found ${results.violations.length} accessibility violations`);
22 | console.log(results.violations);
23 | }
24 | expect(results.violations.length).toBe(0);
25 |
26 | await page.close();
27 | });
28 |
--------------------------------------------------------------------------------
/budget/assert-metrics.spec.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 | const { getBudgetMetricsOfPage, getMatchedPageMetrics, getBudgetMetricByPageMetricName } = require('./helpers');
3 |
4 | // Example page metrics
5 | // [
6 | // { name: 'Timestamp', value: 66567.150449 },
7 | // { name: 'AudioHandlers', value: 0 },
8 | // { name: 'Documents', value: 8 },
9 | // { name: 'Frames', value: 3 },
10 | // { name: 'JSEventListeners', value: 34 },
11 | // { name: 'LayoutObjects', value: 455 },
12 | // { name: 'MediaKeySessions', value: 0 },
13 | // { name: 'MediaKeys', value: 0 },
14 | // { name: 'Nodes', value: 970 },
15 | // { name: 'Resources', value: 74 },
16 | // { name: 'ContextLifecycleStateObservers', value: 0 },
17 | // { name: 'V8PerContextDatas', value: 4 },
18 | // { name: 'WorkerGlobalScopes', value: 0 },
19 | // { name: 'UACSSResources', value: 0 },
20 | // { name: 'RTCPeerConnections', value: 0 },
21 | // { name: 'ResourceFetchers', value: 8 },
22 | // { name: 'AdSubframes', value: 0 },
23 | // { name: 'DetachedScriptStates', value: 2 },
24 | // { name: 'LayoutCount', value: 13 },
25 | // { name: 'RecalcStyleCount', value: 22 },
26 | // { name: 'LayoutDuration', value: 0.067929 },
27 | // { name: 'RecalcStyleDuration', value: 0.029508 },
28 | // { name: 'ScriptDuration', value: 0.122922 },
29 | // { name: 'V8CompileDuration', value: 0.003031 },
30 | // { name: 'TaskDuration', value: 0.336774 },
31 | // { name: 'TaskOtherDuration', value: 0.116415 },
32 | // { name: 'ThreadTime', value: 0.275266 },
33 | // { name: 'JSHeapUsedSize', value: 7816504 },
34 | // { name: 'JSHeapTotalSize', value: 11096064 },
35 | // { name: 'FirstMeaningfulPaint', value: 66565.452541 },
36 | // { name: 'DomContentLoaded', value: 66565.386449 },
37 | // { name: 'NavigationStart', value: 66564.624457 }
38 | // ]
39 |
40 | const assertMetricsOnUrl = async (siteUrl) => {
41 | const page = await this.browser.newPage();
42 | const protocol = await page.target().createCDPSession();
43 | await protocol.send('Performance.enable');
44 |
45 | await page.goto(siteUrl, { waitUntil: 'networkidle0' });
46 | const budgetMetrics = await getBudgetMetricsOfPage(page);
47 | const { metrics: pageMetrics } = await protocol.send('Performance.getMetrics');
48 |
49 | const matchedMetrics = getMatchedPageMetrics(pageMetrics, budgetMetrics);
50 |
51 | matchedMetrics.forEach(pageMetric => {
52 | expect(pageMetric.value).toBeLessThan(getBudgetMetricByPageMetricName(budgetMetrics, pageMetric));
53 | });
54 |
55 | await page.close();
56 | };
57 |
58 | beforeAll(async () => {
59 | this.browser = await puppeteer.launch();
60 | });
61 |
62 | afterAll(async () => {
63 | await this.browser.close();
64 | });
65 |
66 | test('asserts budget performance metrics on the main page', async() => {
67 | await assertMetricsOnUrl('https://pptr.dev');
68 | }, 30000);
69 |
70 | test('asserts budget performance metrics on api page', async() => {
71 | await assertMetricsOnUrl('https://pptr.dev/api');
72 | }, 30000);
73 |
--------------------------------------------------------------------------------
/budget/budget.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "path": "/",
4 | "perfMetrics": [
5 | {
6 | "metric": "JSEventListeners",
7 | "budget": 100
8 | },
9 | {
10 | "metric": "Nodes",
11 | "budget": 2000
12 | },
13 | {
14 | "metric": "JSHeapUsedSize",
15 | "budget": 20000000
16 | }
17 | ]
18 | },
19 | {
20 | "path": "/vacatures",
21 | "perfMetrics": [
22 | {
23 | "metric": "Resources",
24 | "budget": 80
25 | }
26 | ]
27 | }
28 | ]
29 |
--------------------------------------------------------------------------------
/budget/helpers.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const { promisify } = require('util');
3 | const readFileAsync = promisify(fs.readFile);
4 |
5 | const bytesToMb = (bytes) => {
6 | return bytes/1e+6;
7 | };
8 |
9 | const getTimeFromPerformanceMetrics = (metrics, name) =>
10 | metrics.metrics.find(x => x.name === name).value * 1000;
11 |
12 | const parsePerformanceMetrics = (metrics, ...metricNames) => {
13 | const parsedData = {};
14 | const navigationStart = getTimeFromPerformanceMetrics(
15 | metrics,
16 | 'NavigationStart'
17 | );
18 |
19 | metricNames.forEach(metricName => {
20 | parsedData[metricName] =
21 | getTimeFromPerformanceMetrics(metrics, metricName) - navigationStart;
22 | });
23 |
24 | return parsedData;
25 | };
26 |
27 | const getCustomMetric = (page, metricName) =>
28 | new Promise(resolve =>
29 | page.on('metrics', ({ title, metrics }) => {
30 | if (title === metricName) {
31 | resolve(metrics.Timestamp * 1000);
32 | }
33 | })
34 | );
35 |
36 | const getPath = (page) => {
37 | return page.evaluate(() => document.location.pathname);
38 | };
39 |
40 | const getBudgetMetrics = async () => {
41 | const budgetMetrics = await readFileAsync('./budget.json', { encoding: 'utf8' });
42 | return JSON.parse(budgetMetrics);
43 | };
44 |
45 | const getBudgetMetricsForPath = async (path) => {
46 | const metrics = await getBudgetMetrics();
47 | const metricForPath = metrics.find(metric => metric.path === path);
48 |
49 | if (metricForPath) {
50 | return metricForPath.perfMetrics;
51 | }
52 |
53 | return null;
54 | };
55 |
56 | const getBudgetMetricsOfPage = async (page) => {
57 | const path = await getPath(page);
58 | return getBudgetMetricsForPath(path);
59 | };
60 |
61 | const getMatchedPageMetrics = (pageMetrics, budgetMetrics) => {
62 | return pageMetrics.filter((pageMetric) =>
63 | budgetMetrics.some(budgetMetric => budgetMetric.metric === pageMetric.name));
64 | };
65 |
66 | const getBudgetMetricByPageMetricName = (budgetMetrics, pageMetric) => {
67 | return budgetMetrics.find(budgetMetric => budgetMetric.metric === pageMetric.name).budget
68 | };
69 |
70 | module.exports = {
71 | getBudgetMetricByPageMetricName,
72 | getTimeFromPerformanceMetrics,
73 | parsePerformanceMetrics,
74 | getBudgetMetricsOfPage,
75 | getBudgetMetricsForPath,
76 | getMatchedPageMetrics,
77 | getBudgetMetrics,
78 | getCustomMetric,
79 | bytesToMb,
80 | getPath
81 | };
82 |
--------------------------------------------------------------------------------
/cert-expiration.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 |
3 | (async () => {
4 | const siteUrl = 'https://pptr.dev';
5 | const browser = await puppeteer.launch();
6 | const page = await browser.newPage();
7 |
8 | page.on('response', (resp) => {
9 | const url = resp.url();
10 | if (url === siteUrl) {
11 | const secDetails = resp.securityDetails();
12 | const ts = Math.floor((new Date()).getTime() / 1000);
13 | console.log((Math.floor((secDetails.validTo() - ts) / 86400)), 'days to expire');
14 | }
15 | });
16 |
17 | await page.goto(siteUrl, { waitUntil: 'networkidle0' });
18 | await page.close();
19 | await browser.close();
20 | })();
21 |
--------------------------------------------------------------------------------
/code-coverage.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 | const pti = require('puppeteer-to-istanbul');
3 |
4 | // Inspiration: https://github.com/trentmwillis/devtools-protocol-demos/blob/master/testing-demos/code-coverage.js
5 |
6 | (async () => {
7 | const browser = await puppeteer.launch();
8 |
9 | const page = await browser.newPage();
10 |
11 | await page.coverage.startJSCoverage();
12 |
13 | await page.goto('https://pptr.dev');
14 |
15 | const jsCoverage = await page.coverage.stopJSCoverage();
16 | pti.write(jsCoverage);
17 |
18 | await page.close();
19 |
20 | await browser.close();
21 | })();
22 |
--------------------------------------------------------------------------------
/dark-mode.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 |
3 | (async () => {
4 | const browser = await puppeteer.launch();
5 |
6 | const page = await browser.newPage();
7 |
8 | await page.goto('https://googlechromelabs.github.io/dark-mode-toggle/demo/index.html');
9 | await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'light' }]);
10 | await page.waitForTimeout(200);
11 | await page.screenshot({ path: 'light.jpg', type: 'jpeg', omitBackground: true });
12 | await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]);
13 | await page.waitForTimeout(200);
14 | await page.screenshot({ path: 'dark.jpg', type: 'jpeg', omitBackground: true });
15 | await browser.close();
16 | })();
17 |
--------------------------------------------------------------------------------
/dom-snapshot.spec.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 |
3 | test('regression testing page dom snapshot', async() => {
4 | const browser = await puppeteer.launch();
5 |
6 | const page = await browser.newPage();
7 |
8 | await page.goto('https://pptr.dev');
9 |
10 | expect(await page.content()).toMatchSnapshot();
11 |
12 | await page.close();
13 |
14 | await browser.close();
15 | });
16 |
--------------------------------------------------------------------------------
/element-to-pdf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Google Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author ebidel@ (Eric Bidelman)
17 | */
18 |
19 | /**
20 | * Takes a screenshot of the latest tweet in a user's timeline and creates a
21 | * PDF of it. Shows how to use Puppeteer to:
22 | *
23 | * 1. screenshot a DOM element
24 | * 2. craft an HTML page on-the-fly
25 | * 3. produce an image of the element and PDF of the page with the image embedded
26 | *
27 | * Usage:
28 | * node element-to-pdf.js
29 | * USERNAME=ChromiumDev node element-to-pdf.js
30 | *
31 | * --searchable makes "find in page" work:
32 | * node element-to-pdf.js --searchable
33 | *
34 | * Output:
35 | * tweet.png and tweet.pdf
36 | */
37 |
38 | // Inspiration: https://github.com/GoogleChromeLabs/puppeteer-examples/blob/master/element-to-pdf.js
39 |
40 | const puppeteer = require('puppeteer');
41 |
42 | const username = process.env.USERNAME || 'onderceylan';
43 | const searchable = process.argv.includes('--searchable');
44 |
45 | (async() => {
46 |
47 | const browser = await puppeteer.launch({headless: false});
48 |
49 | const page = await browser.newPage();
50 | await page.setViewport({width: 1200, height: 1000, deviceScaleFactor: 2});
51 | await page.goto(`https://twitter.com/${username}/status/1648736108304297985`);
52 |
53 | await page.waitForSelector('[data-testid="tweet"]', {visible: true});
54 |
55 | await page.$eval('#layers', el => el.remove());
56 |
57 | const overlay = await page.$('[data-testid="tweet"]');
58 | const screenshot = await overlay.screenshot({path: 'tweet.png'});
59 |
60 | await page.setContent(`
61 |
62 |
63 |
64 |
79 |
80 |
81 |
82 |
83 |
84 | `);
85 |
86 | await page.pdf({path: 'tweet.pdf', printBackground: true});
87 | await browser.close();
88 | })();
89 |
--------------------------------------------------------------------------------
/fps.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onderceylan/puppeteer-demos/bdffbe3b9a14f00f07c29614eea90310051a2eed/fps.jpeg
--------------------------------------------------------------------------------
/fps.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 |
3 | (async () => {
4 | const browser = await puppeteer.launch({
5 | headless: false,
6 | });
7 | const page = await browser.newPage();
8 | const protocol = await page.target().createCDPSession();
9 | await protocol.send('Overlay.setShowFPSCounter', { show: true });
10 | await page.goto('https://pptr.dev');
11 |
12 | // Do graphical regressions here by interacting with the page
13 | await protocol.send('Input.synthesizeScrollGesture', {
14 | x: 100,
15 | y: 100,
16 | yDistance: -400,
17 | repeatCount: 3
18 | });
19 |
20 | await page.screenshot({
21 | path: 'fps.jpeg',
22 | type: 'jpeg',
23 | clip: {
24 | x:0,
25 | y:0,
26 | width: 370,
27 | height: 370
28 | }
29 | });
30 | await page.close();
31 | await browser.close();
32 | })();
33 |
--------------------------------------------------------------------------------
/memory-leak-heap.spec.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 |
3 | // Inspiration: https://github.com/trentmwillis/devtools-protocol-demos/blob/master/testing-demos/memory-leak-by-heap.js
4 |
5 | beforeAll(async () => {
6 | this.browser = await puppeteer.launch();
7 | });
8 |
9 | afterAll(async () => {
10 | await this.browser.close();
11 | });
12 |
13 | test('asserts memory leak by heap on the main page', async() => {
14 | const page = await this.browser.newPage();
15 | await page.goto('https://pptr.dev');
16 |
17 |
18 | const protocol = await page.target().createCDPSession();
19 | await protocol.send('HeapProfiler.enable');
20 | await protocol.send('HeapProfiler.collectGarbage');
21 |
22 | const startMetrics = await page.metrics();
23 |
24 | // Do memory regressions here by interacting with the page
25 | await protocol.send('Input.synthesizeScrollGesture', {
26 | x: 100,
27 | y: 100,
28 | yDistance: -400,
29 | repeatCount: 3
30 | });
31 |
32 | // Or just keep your app open for a certain amoun of time
33 | await page.waitForTimeout(5000);
34 |
35 | await protocol.send('HeapProfiler.collectGarbage');
36 |
37 | const endMetrics = await page.metrics();
38 |
39 | expect(endMetrics.JSHeapUsedSize < startMetrics.JSHeapUsedSize * 1.1).toBeTruthy();
40 |
41 | await page.close();
42 | }, 30000);
43 |
--------------------------------------------------------------------------------
/memory-leak-proto.spec.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 |
3 | // Inspiration: https://github.com/trentmwillis/devtools-protocol-demos/blob/master/testing-demos/memory-leak-by-prototype.js
4 |
5 | beforeAll(async () => {
6 | this.browser = await puppeteer.launch();
7 | });
8 |
9 | afterAll(async () => {
10 | await this.browser.close();
11 | });
12 |
13 | test('asserts memory leak by prototype on the main page', async() => {
14 | const page = await this.browser.newPage();
15 | await page.goto('https://pptr.dev');
16 |
17 | // Get a handle to the Map object prototype
18 | const mapPrototype = await page.evaluateHandle(() => Map.prototype);
19 |
20 | // Query all map instances into an array
21 | const mapInstances = await page.queryObjects(mapPrototype);
22 |
23 | // Count amount of map objects in heap
24 | const count = await page.evaluate(maps => maps.length, mapInstances);
25 |
26 | // Idea here is to test object instances on the page
27 | // where it's expected to be invalidated
28 | expect(count).toBe(0);
29 |
30 | await page.close();
31 | }, 30000);
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "puppeteer-demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "@d-lab/discord-puppet": "^0.6.4",
14 | "chrome-launcher": "^0.13.1",
15 | "jest": "^25.5.4",
16 | "looks-same": "^7.2.1",
17 | "node-notifier": "^9.0.0",
18 | "nyc": "^15.0.0",
19 | "puppeteer": "^20.1.2",
20 | "puppeteer-to-istanbul": "^1.4.0",
21 | "superstatic": "^6.0.4",
22 | "yargs": "^16.0.3"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pptrgram.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const puppeteer = require('puppeteer');
3 |
4 | (async () => {
5 | // All available filters from cssgram
6 | const filters = [
7 | '1977',
8 | 'aden',
9 | 'amaro',
10 | 'brannan',
11 | 'brooklyn',
12 | 'clarendon',
13 | 'gingham',
14 | 'hudson',
15 | 'inkwell',
16 | 'kelvin',
17 | 'lark',
18 | 'lofi',
19 | 'mayfair',
20 | 'moon',
21 | 'nashville',
22 | 'perpetua',
23 | 'reyes',
24 | 'rise',
25 | 'slumber',
26 | 'stinson',
27 | 'toaster',
28 | 'valencia',
29 | 'walden',
30 | 'willow',
31 | 'xpro2'
32 | ];
33 |
34 | const browser = await puppeteer.launch({
35 | headless: true,
36 | });
37 |
38 | const getImageBase64Url = (imagePath) => {
39 | return `data:image/jpeg;base64,${fs.readFileSync(imagePath, {
40 | encoding: 'base64',
41 | })}`;
42 | };
43 |
44 | await Promise.all(filters.map(async (filter) => {
45 | const page = await browser.newPage();
46 | await page.setContent(`
47 |
68 |
69 |
70 | @onderceylan
71 |
72 | `, { waitUntil: 'networkidle2' });
73 |
74 | await page.addStyleTag({
75 | url: 'https://cdnjs.cloudflare.com/ajax/libs/cssgram/0.1.10/cssgram.min.css'
76 | });
77 |
78 | // Get original image dimensions
79 | const { width, height } = await page.evaluate(() => {
80 | return (({naturalWidth: width, naturalHeight: height}) => ({width, height}))(document.querySelector('img'));
81 | });
82 |
83 | await page.setViewport({ width, height });
84 |
85 | await page.screenshot({
86 | path: `pptgram/pptrgram-${filter}.jpeg`,
87 | type: 'jpeg',
88 | quality: 70,
89 | fullPage: true,
90 | });
91 |
92 | await page.close();
93 | }));
94 |
95 | await browser.close();
96 | })();
97 |
--------------------------------------------------------------------------------
/pptrjourney.js:
--------------------------------------------------------------------------------
1 | const {MidjourneyPuppet, options} = require("@d-lab/discord-puppet");
2 |
3 | // See prerequisites at https://github.com/Draym/discord-puppet#prerequisite
4 |
5 | (async () => {
6 | const config = options(
7 | process.env.DISCORD_USERNAME,
8 | process.env.DISCORD_PASSWORD,
9 | [],
10 | process.env.DISCORD_USER_DATA_DIR
11 | )
12 | const puppet = new MidjourneyPuppet(config)
13 | await puppet.start()
14 | await puppet.clickServer("PptrJourney")
15 | await puppet.clickChannel("art")
16 |
17 | const msg2 = await puppet.imagine(`Your awesome prompt here!`)
18 | console.log("MJY image: ", msg2)
19 | })();
20 |
21 |
--------------------------------------------------------------------------------
/sample.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onderceylan/puppeteer-demos/bdffbe3b9a14f00f07c29614eea90310051a2eed/sample.jpg
--------------------------------------------------------------------------------
/security.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 |
3 | (async () => {
4 | const siteUrl = 'https://pptr.dev';
5 | const browser = await puppeteer.launch();
6 | const page = await browser.newPage();
7 |
8 | const protocol = await page.target().createCDPSession();
9 | await protocol.send('Security.enable');
10 |
11 | protocol.on('Security.securityStateChanged', (state) => {
12 | console.log(state);
13 | });
14 |
15 | await page.goto(siteUrl, { waitUntil: 'networkidle0' });
16 | await page.close();
17 | await browser.close();
18 | })();
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/side-by-side-pageload.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Google Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author ebidel@ (Eric Bidelman)
17 | */
18 |
19 | /**
20 | * Launches one or more URLs in different browser windows to visually compare
21 | * the page loads side-by-side. Options to center the windows on screen,
22 | * emulate mobile devices, and toggle CPU/Network throttling.
23 | *
24 | * Usage:
25 | *
26 | * node side-by-side-pageload.js -h
27 | */
28 |
29 | // Inspiration: https://github.com/GoogleChromeLabs/puppeteer-examples/blob/master/side-by-side-pageload.js
30 |
31 | const puppeteer = require('puppeteer');
32 | const devices = require('puppeteer/DeviceDescriptors');
33 | const iphone6 = puppeteer.KnownDevices['iPhone 6'];
34 |
35 | const argv = require('yargs')
36 | .options({
37 | 'mobile': {
38 | alias: 'm',
39 | describe: 'Emulate a mobile viewport',
40 | default: true,
41 | },
42 | 'throttle': {
43 | describe: 'Throttles CPU by 4x and network to "Slow 3G"',
44 | default: true,
45 | },
46 | 'center': {
47 | alias: 'c',
48 | describe: 'Centers the the windows on screen',
49 | default: true,
50 | },
51 | 'url': {
52 | alias: 'u',
53 | describe: 'URL to load',
54 | demandOption: true,
55 | },
56 | 'space': {
57 | alias: 's',
58 | describe: 'Spaces between windows (when emulating mobile)',
59 | default: 20,
60 | },
61 | 'timeout': {
62 | alias: 't',
63 | describe: 'Timeout after page finish loading before closing the browers',
64 | default: 3000,
65 | },
66 | })
67 | .array('url')
68 | .help()
69 | .example('$0 --url https://devwebfeed.appspot.com https://devwebfeed.appspot.com/ssr')
70 | .example('$0 --no-throttle --no-mobile -u https://devwebfeed.appspot.com https://devwebfeed.appspot.com/ssr')
71 | .example('$0 -u https://www.bing.com/ https://www.google.com/ https://www.yahoo.com/')
72 | .wrap(null)
73 | .argv;
74 |
75 | const urls = argv.url.length ? argv.url : [
76 | 'https://devwebfeed.appspot.com/',
77 | 'https://devwebfeed.appspot.com/ssr',
78 | ];
79 |
80 | const CENTER_WINDOWS_ON_SCREEN = argv.center;
81 | const SPACE_BETWEEN_WINDOWS = argv.space;
82 | const MOBILE = argv.mobile;
83 | const THROTTLE = argv.throttle;
84 | const TIMEOUT_AFTER_LOAD = argv.timeout;
85 | const DEFAULT_VIEWPORT = {width: 1000, height: 800, deviceScaleFactor: 2};
86 |
87 | const sleep = (timeout) => new Promise(r => setTimeout(r, timeout));
88 |
89 | async function launch(position, screen) {
90 | const totalSpacerWidthAddition = SPACE_BETWEEN_WINDOWS * (urls.length - 1);
91 | const totalWidthOfWindows = urls.length * DEFAULT_VIEWPORT.width;
92 | const totalWidthOfWindowsWithSpacers = totalWidthOfWindows + totalSpacerWidthAddition;
93 |
94 | const centerScreenX = screen.width / 2;
95 | const centerScreenY = screen.height / 2;
96 |
97 | let dx = DEFAULT_VIEWPORT.width * position;
98 | dx += SPACE_BETWEEN_WINDOWS * position;
99 |
100 | const x = Math.floor(centerScreenX - (totalWidthOfWindowsWithSpacers / 2) + dx);
101 | const y = Math.floor(centerScreenY - (DEFAULT_VIEWPORT.height / 2));
102 |
103 | const browser = await puppeteer.launch({
104 | headless: false,
105 | args: [
106 | `--window-size=${DEFAULT_VIEWPORT.width},${DEFAULT_VIEWPORT.height}`,
107 | CENTER_WINDOWS_ON_SCREEN ? `--window-position=${x},${y}` : `--window-position=${dx},0`,
108 | ],
109 | });
110 |
111 | const page = await browser.newPage();
112 | if (MOBILE) {
113 | await page.emulate(iphone6);
114 | } else {
115 | await page.setViewport(DEFAULT_VIEWPORT);
116 | }
117 |
118 | if (THROTTLE) {
119 | const client = await page.target().createCDPSession();
120 | // Emulate "Slow 3G" according to WebPageTest.
121 | await client.send('Network.emulateNetworkConditions', {
122 | offline: false,
123 | latency: 400,
124 | downloadThroughput: Math.floor(400 * 1024 / 8), // 400 Kbps
125 | uploadThroughput: Math.floor(400 * 1024 / 8) // 400 Kbps
126 | });
127 | await client.send('Emulation.setCPUThrottlingRate', {rate: 4});
128 | }
129 |
130 | return page;
131 | }
132 |
133 | (async () => {
134 |
135 | const browser = await puppeteer.launch();
136 | const page = await browser.newPage();
137 |
138 | const screen = await page.evaluate(() => {
139 | return {width: window.screen.availWidth, height: window.screen.availHeight};
140 | });
141 | await browser.close();
142 |
143 | // Take up full desktop space or emulate mobile.
144 | DEFAULT_VIEWPORT.width = MOBILE ? iphone6.viewport.width : Math.floor(screen.width / urls.length);
145 | DEFAULT_VIEWPORT.height = MOBILE ? iphone6.viewport.height : screen.height;
146 |
147 | const pages = await Promise.all(urls.map((url, i) => launch(i, screen)));
148 |
149 | const start = Date.now();
150 |
151 | const waitForPage = async pos => {
152 | const page = pages[pos];
153 | const url = urls[pos];
154 | return page.goto(url, {waitUntil: 'networkidle2'})
155 | .then(() => Date.now());
156 | };
157 |
158 | const stopTimes = await Promise.all(urls.map((url, i) => waitForPage(i)));
159 | stopTimes.forEach((stopTime, i) => console.log(`Page ${i + 1} took ${stopTime - start} ms to reach network idle`));
160 |
161 | await sleep(TIMEOUT_AFTER_LOAD);
162 |
163 | await Promise.all(pages.map(page => page.browser().close()));
164 |
165 | })();
166 |
--------------------------------------------------------------------------------
/speech.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Google Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | * @author ebidel@ (Eric Bidelman)
17 | */
18 |
19 | /**
20 | * Uses the web speech synth API to make the browser talk.
21 | *
22 | * Run it:
23 | * node speech.js -t Hello there, my name is Jarvis.
24 | * node speech.js -t Read anything good lately?
25 | * CHROME_PATH=/path/to/chrome node speech.js -t hi and bye!
26 | */
27 |
28 | // Inspiration: https://github.com/GoogleChromeLabs/puppeteer-examples/blob/master/speech.js
29 |
30 | const argv = require('yargs').argv;
31 | const puppeteer = require('puppeteer');
32 |
33 | const DEFAULT_TXT = 'Hello there, my name is Puppeteer. I am controlling your browser.';
34 | const DEFAULT_VOICE = 'Milena';
35 |
36 | const executablePath = process.env.CHROME_PATH ||
37 | '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome';
38 |
39 | const html = (voiceName) => `
40 | speak
41 |
42 | `;
70 |
71 | (async() => {
72 |
73 | const browser = await puppeteer.launch({
74 | executablePath, // Note: need Chrome (not Chromium) to use non-default voices.
75 | headless: false, // Speech synth API doesn't work in headless. crbug.com/815388
76 | args: [
77 | '--window-size=0,0', // Launch baby window for fun.
78 | '--window-position=0,0',
79 | '--enable-speech-dispatcher', // Needed for Linux?
80 | ],
81 | });
82 |
83 | const page = await browser.newPage();
84 |
85 | // Clever way to "communicate with page". Know when speech is done.
86 | page.on('console', async msg => {
87 | if (msg.text() === 'SPEECH_DONE') {
88 | await browser.close();
89 | }
90 | });
91 |
92 | const text = argv.text || DEFAULT_TXT;
93 | const voiceName = argv.voice || DEFAULT_VOICE;
94 |
95 | await page.evaluateOnNewDocument(text => window.TEXT2SPEECH = text, text);
96 |
97 | // Cause a navigation so the evaluateOnNewDocument kicks in.
98 | await page.goto(`data:text/html,${html(voiceName)}`);
99 |
100 | const button = await page.$('button');
101 | button.click();
102 |
103 | })();
104 |
--------------------------------------------------------------------------------
/tensor-sample.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onderceylan/puppeteer-demos/bdffbe3b9a14f00f07c29614eea90310051a2eed/tensor-sample.jpg
--------------------------------------------------------------------------------
/tensorflow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/tensorflow.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 |
3 | (async () => {
4 |
5 | const browser = await puppeteer.launch({
6 | headless: true,
7 | });
8 |
9 | const page = await browser.newPage();
10 |
11 | await page.goto(`http://localhost:8002/tensorflow.html`);
12 |
13 | const result = await page.evaluate(() => {
14 | const img = document.getElementById('img');
15 |
16 | // Load the model.
17 | return cocoSsd.load().then(model => model.detect(img))
18 | });
19 |
20 | console.log(result);
21 |
22 | await page.close();
23 |
24 | await browser.close();
25 | })();
26 |
--------------------------------------------------------------------------------
/timeline-trace.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 |
3 | // Example on how to use this data: https://michaljanaszek.com/blog/test-website-performance-with-puppeteer
4 | // Timeline viewer: https://chromedevtools.github.io/timeline-viewer/
5 |
6 | (async () => {
7 | const browser = await puppeteer.launch(({
8 | headless: true,
9 | }));
10 |
11 | const page = await browser.newPage();
12 |
13 | await page.tracing.start({ path: 'trace.json' });
14 | await page.goto('https://www.google.com');
15 | await page.waitForTimeout(2000);
16 | await page.tracing.stop();
17 |
18 | await page.close();
19 |
20 | await browser.close();
21 | })();
22 |
--------------------------------------------------------------------------------
/visual-regression.spec.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 | const fs = require('fs');
3 | const looksSame = require('looks-same');
4 | // You can switch to using https://github.com/mapbox/pixelmatch#nodejs
5 | // If you prefer to keep a diff image in your reports
6 |
7 | // Inspiration: https://github.com/trentmwillis/devtools-protocol-demos/blob/master/testing-demos/visual-regression.js
8 |
9 | const takeScreenshot = async (page, title) => {
10 | if (!fs.existsSync('./.screenshots')) {
11 | fs.mkdirSync('./.screenshots');
12 | }
13 | const filePath = `./.screenshots/${title}.png`;
14 | if (fs.existsSync(filePath)) {
15 | const newFilePath = `./.screenshots/${title}-new.png`;
16 | await page.screenshot({
17 | path: newFilePath,
18 | fullPage: true
19 | });
20 | const result = await new Promise(resolve => looksSame(filePath, newFilePath, (err, equal) => resolve(equal)));
21 | fs.unlinkSync(newFilePath);
22 | return result;
23 | } else {
24 | await page.screenshot({
25 | path: filePath,
26 | fullPage: true
27 | });
28 | return true;
29 | }
30 | };
31 |
32 | beforeAll(async () => {
33 | this.browser = await puppeteer.launch();
34 | });
35 |
36 | afterAll(async () => {
37 | await this.browser.close();
38 | });
39 |
40 | test('asserts visual regression on the main page', async() => {
41 | const page = await this.browser.newPage();
42 | await page.goto('https://pptr.dev');
43 |
44 | expect(await takeScreenshot(page, 'main-page.1')).toBeTruthy();
45 |
46 | await page.close();
47 | }, 20000);
48 |
--------------------------------------------------------------------------------
/whatsapp/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "morning-hail"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/whatsapp/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | firebase-debug.log*
8 |
9 | # Firebase cache
10 | .firebase/
11 |
12 | # Firebase config
13 |
14 | # Uncomment this if you'd like others to create their own Firebase project.
15 | # For a team working on the same Firebase project(s), it is recommended to leave
16 | # it commented so all members can deploy to the same project(s) in .firebaserc.
17 | # .firebaserc
18 |
19 | # Runtime data
20 | pids
21 | *.pid
22 | *.seed
23 | *.pid.lock
24 |
25 | # Directory for instrumented libs generated by jscoverage/JSCover
26 | lib-cov
27 |
28 | # Coverage directory used by tools like istanbul
29 | coverage
30 |
31 | # nyc test coverage
32 | .nyc_output
33 |
34 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
35 | .grunt
36 |
37 | # Bower dependency directory (https://bower.io/)
38 | bower_components
39 |
40 | # node-waf configuration
41 | .lock-wscript
42 |
43 | # Compiled binary addons (http://nodejs.org/api/addons.html)
44 | build/Release
45 |
46 | # Dependency directories
47 | node_modules/
48 |
49 | # Optional npm cache directory
50 | .npm
51 |
52 | # Optional eslint cache
53 | .eslintcache
54 |
55 | # Optional REPL history
56 | .node_repl_history
57 |
58 | # Output of 'npm pack'
59 | *.tgz
60 |
61 | # Yarn Integrity file
62 | .yarn-integrity
63 |
64 | # dotenv environment variables file
65 | .env
66 |
67 | qr.png
68 | chrome-user.zip
69 |
--------------------------------------------------------------------------------
/whatsapp/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "functions": {
3 | "predeploy": [
4 | "npm --prefix \"$RESOURCE_DIR\" run lint"
5 | ]
6 | },
7 | "storage": {
8 | "rules": "storage.rules"
9 | },
10 | "emulators": {
11 | "functions": {
12 | "port": 5001
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/whatsapp/functions/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "parserOptions": {
3 | // Required for certain syntax usages
4 | "ecmaVersion": 2017
5 | },
6 | "plugins": [
7 | "promise"
8 | ],
9 | "extends": "eslint:recommended",
10 | "rules": {
11 | // Removed rule "disallow the use of console" from recommended eslint rules
12 | "no-console": "off",
13 |
14 | // Removed rule "disallow multiple spaces in regular expressions" from recommended eslint rules
15 | "no-regex-spaces": "off",
16 |
17 | // Removed rule "disallow the use of debugger" from recommended eslint rules
18 | "no-debugger": "off",
19 |
20 | // Removed rule "disallow unused variables" from recommended eslint rules
21 | "no-unused-vars": "off",
22 |
23 | // Removed rule "disallow mixed spaces and tabs for indentation" from recommended eslint rules
24 | "no-mixed-spaces-and-tabs": "off",
25 |
26 | // Removed rule "disallow the use of undeclared variables unless mentioned in /*global */ comments" from recommended eslint rules
27 | "no-undef": "off",
28 |
29 | // Warn against template literal placeholder syntax in regular strings
30 | "no-template-curly-in-string": 1,
31 |
32 | // Warn if return statements do not either always or never specify values
33 | "consistent-return": 1,
34 |
35 | // Warn if no return statements in callbacks of array methods
36 | "array-callback-return": 1,
37 |
38 | // Require the use of === and !==
39 | "eqeqeq": 2,
40 |
41 | // Disallow the use of alert, confirm, and prompt
42 | "no-alert": 2,
43 |
44 | // Disallow the use of arguments.caller or arguments.callee
45 | "no-caller": 2,
46 |
47 | // Disallow null comparisons without type-checking operators
48 | "no-eq-null": 2,
49 |
50 | // Disallow the use of eval()
51 | "no-eval": 2,
52 |
53 | // Warn against extending native types
54 | "no-extend-native": 1,
55 |
56 | // Warn against unnecessary calls to .bind()
57 | "no-extra-bind": 1,
58 |
59 | // Warn against unnecessary labels
60 | "no-extra-label": 1,
61 |
62 | // Disallow leading or trailing decimal points in numeric literals
63 | "no-floating-decimal": 2,
64 |
65 | // Warn against shorthand type conversions
66 | "no-implicit-coercion": 1,
67 |
68 | // Warn against function declarations and expressions inside loop statements
69 | "no-loop-func": 1,
70 |
71 | // Disallow new operators with the Function object
72 | "no-new-func": 2,
73 |
74 | // Warn against new operators with the String, Number, and Boolean objects
75 | "no-new-wrappers": 1,
76 |
77 | // Disallow throwing literals as exceptions
78 | "no-throw-literal": 2,
79 |
80 | // Require using Error objects as Promise rejection reasons
81 | "prefer-promise-reject-errors": 2,
82 |
83 | // Enforce “for” loop update clause moving the counter in the right direction
84 | "for-direction": 2,
85 |
86 | // Enforce return statements in getters
87 | "getter-return": 2,
88 |
89 | // Disallow await inside of loops
90 | "no-await-in-loop": 2,
91 |
92 | // Disallow comparing against -0
93 | "no-compare-neg-zero": 2,
94 |
95 | // Warn against catch clause parameters from shadowing variables in the outer scope
96 | "no-catch-shadow": 1,
97 |
98 | // Disallow identifiers from shadowing restricted names
99 | "no-shadow-restricted-names": 2,
100 |
101 | // Enforce return statements in callbacks of array methods
102 | "callback-return": 2,
103 |
104 | // Require error handling in callbacks
105 | "handle-callback-err": 2,
106 |
107 | // Warn against string concatenation with __dirname and __filename
108 | "no-path-concat": 1,
109 |
110 | // Prefer using arrow functions for callbacks
111 | "prefer-arrow-callback": 1,
112 |
113 | // Return inside each then() to create readable and reusable Promise chains.
114 | // Forces developers to return console logs and http calls in promises.
115 | "promise/always-return": 2,
116 |
117 | //Enforces the use of catch() on un-returned promises
118 | "promise/catch-or-return": 2,
119 |
120 | // Warn against nested then() or catch() statements
121 | "promise/no-nesting": 1
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/whatsapp/functions/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | secret/
--------------------------------------------------------------------------------
/whatsapp/functions/helpers.js:
--------------------------------------------------------------------------------
1 | const admin = require('firebase-admin');
2 | const unzipper = require('unzipper');
3 | const fs = require('fs');
4 | const os = require('os');
5 | const path = require('path');
6 | const USER_FOLDER_NAME = 'chrome-user';
7 | const TEMP_USER_FOLDER_PATH = path.resolve(os.tmpdir(), USER_FOLDER_NAME);
8 |
9 | admin.initializeApp();
10 |
11 | const listStorageFiles = () => {
12 | return admin.storage().bucket().getFiles();
13 | };
14 |
15 | const downloadUserFile = async (filePath) => {
16 | const tempFilePath = path.join(os.tmpdir(), filePath);
17 | const bucket = admin.storage().bucket();
18 | await bucket.file(filePath).download({ destination: tempFilePath });
19 | return tempFilePath;
20 | };
21 |
22 | const saveFileToStorage = (filePath, data, options = null) => {
23 | // const tempFilePath = path.join(os.tmpdir(), filePath);
24 | const bucket = admin.storage().bucket();
25 | return bucket.file(filePath).save(data, options);
26 | };
27 |
28 | const unzipUserData = async (filePath) => {
29 | return new Promise((resolve, reject) => {
30 | fs.createReadStream(filePath).pipe(unzipper.Extract({ path: TEMP_USER_FOLDER_PATH })).on('close', resolve).on('error', reject);
31 | });
32 | };
33 |
34 | const getRandomElem = (array) => array[Math.floor(Math.random() * array.length)];
35 |
36 | const getRandomEmoji = () => {
37 | const emojis = ['😘', '😙', '👋', '🤗', '🥰', '🤓', '🤩'];
38 | return getRandomElem(emojis);
39 | };
40 |
41 | const getTodaysMessage = () => {
42 | const awesomeWishes = ['güzel', 'şahane', 'keyifli', 'huzurlu', 'harika'];
43 | const weekendWishes = [ ...awesomeWishes, 'eğlenceli', 'bol dinlenmeli', 'bol gezmeli'];
44 | const weekDayWishes = [ ...awesomeWishes, 'bereketli', 'başarılı', 'verimli', 'sağlıklı'];
45 | const kisses = ['öpüyorum', 'öpüldünüz', 'öpüyore', 'öptüm'];
46 | const hails = ['Gunaydın', 'Gününüz aydın', 'Günaydınlar'];
47 | const address = ['sevgili ailem', 'canım ailem', 'ceylanos', 'canlar'];
48 | const who = ['', ' herkese'];
49 | const comma = ['', ','];
50 |
51 | let date = new Date();
52 | let day = date.getDay();
53 |
54 | // Randomizing the message a bit so my mom doesn't suspect automation
55 | const randomMessage = `${getRandomElem(hails)} ${getRandomElem(address)}${getRandomElem(comma)}${getRandomElem(who)} :wish: bir gün olsun ${getRandomElem(kisses)} ${getRandomEmoji()}`;
56 |
57 | switch (day) {
58 | case 5:
59 | // Because Friday is a sacred day for my parents, message changes a bit
60 | return randomMessage.replace(':wish: bir gün olsun', 'hayırlı cumalar');
61 | case 6:
62 | // Because we like to hail the weekend on saturday mornings, yay!
63 | return randomMessage.replace(':wish:', getRandomElem(weekendWishes)).replace('gün', 'haftasonu');
64 | case 0:
65 | // Because we enjoy stressing it's Sunday :)
66 | return randomMessage.replace(':wish:', getRandomElem(weekendWishes)).replace('gün', 'pazar');
67 | case 1:
68 | // Because we enjoy stressing it's the week start
69 | return randomMessage.replace(':wish:', getRandomElem(weekDayWishes)).replace('gün', 'hafta');
70 | default:
71 | return randomMessage.replace(':wish:', getRandomElem(weekDayWishes));
72 | }
73 | };
74 |
75 | // Checks if session is expired and qr code is shown
76 | // Saves qr code as qr.png image and logs it to console as base64 encoded string
77 | const checkSessionValidityAndSaveQR = async (page) => {
78 | const qrImgEl = await page.$x('//canvas[@aria-label="Scan me!"]');
79 |
80 | if (qrImgEl.length > 0) {
81 | const img = qrImgEl[0];
82 | try {
83 | await img.screenshot({ path: 'qr.png' });
84 | console.log('Saved QR code as qr.png');
85 | } catch (e) {
86 | console.log(`Won't save the QR code, authenticate again`);
87 | }
88 | throw new Error('Session is expired, need to authenticate again');
89 | }
90 | };
91 |
92 | // Forcefully capture the session when there's a session conflict, aka 'Use Here' prompt
93 | const forcefullyCaptureSession = async (page) => {
94 | await page.exposeFunction('onDomUpdate', async (innerText) => {
95 | if (innerText.toLowerCase().includes('use here')) {
96 | console.log(`"Use here" button is shown`);
97 | const useHereBtn = await page.$x('//div[@role="button"][text()="Use Here"]');
98 | if (useHereBtn.length > 0) {
99 | console.log(`Clicking`);
100 | await useHereBtn[0].click();
101 | }
102 | }
103 | });
104 |
105 | await page.evaluate(() => {
106 | const observer = new MutationObserver((mutations) => {
107 | for(let mutation of mutations) {
108 | if(mutation.addedNodes.length) {
109 | onDomUpdate(mutation.addedNodes[0].innerText);
110 | }
111 | }
112 | });
113 | observer.observe(document.querySelector("body"), { attributes: false, childList: true, subtree: true });
114 | });
115 | };
116 |
117 | const waitForAppLoad = async (page) => {
118 | // WhatsApp has it's own loading mechanism detached from native page load events
119 | await page.waitForSelector('#startup', { hidden: true });
120 | await page.waitForTimeout(1000);
121 | };
122 |
123 | const sendMessageToGroup = async (page, message, groupName, dryRun = false) => {
124 | const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3641.0 Safari/537.36';
125 | try {
126 | // WhatsApp web tries to detect headless chrome so faking the user agent is necessary
127 | await page.setUserAgent(USER_AGENT);
128 | await page.goto('https://web.whatsapp.com/', { waitUntil: 'networkidle0', timeout: 0 });
129 |
130 | await forcefullyCaptureSession(page);
131 | await waitForAppLoad(page);
132 | await checkSessionValidityAndSaveQR(page);
133 |
134 | await page.waitForSelector('#side div[contenteditable="true"]');
135 | await page.type('#side div[contenteditable="true"]', groupName);
136 | await page.waitForSelector(`#pane-side span[title="${groupName}"]`, { visible: true });
137 | await page.click(`span[title="${groupName}"`);
138 | await page.waitForSelector('footer .copyable-text', { visible: true });
139 | await page.type('footer .copyable-text', message);
140 | if (dryRun === false) {
141 | await page.keyboard.press('Enter');
142 | }
143 | await page.waitForTimeout(1000);
144 | console.log(`Message "${message}" sent to group "${groupName}"`);
145 | } catch (e) {
146 | console.error(`There was an error on automated flow`);
147 | const screen = await page.screenshot({ fullPage: true });
148 | const dom = await page.content();
149 | await saveFileToStorage('screen.png', screen, { contentType: 'image/png' });
150 | await saveFileToStorage('dom.html', dom, { contentType: 'text/html' });
151 | console.log('Saved screenshot to the storage');
152 | console.log('Saved DOM to the storage');
153 | throw e;
154 | }
155 | };
156 |
157 | module.exports = {
158 | getTodaysMessage,
159 | sendMessageToGroup,
160 | listStorageFiles,
161 | downloadUserFile,
162 | saveFileToStorage,
163 | unzipUserData,
164 | USER_FOLDER_NAME,
165 | TEMP_USER_FOLDER_PATH
166 | };
167 |
--------------------------------------------------------------------------------
/whatsapp/functions/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * WhatsApp Morning Hail!
3 | * Firebase/Google Cloud function to hail parents on WhatsApp automatically in the morning that is executed daily via scheduler!
4 | *
5 | * It keeps your WhatsApp session in Cloud Storage over Chrome's user data directory
6 | * And sends a message to a WhatsApp group every morning with headless chrome instance using Puppeteer on a cloud function
7 | *
8 | * Although I use it personally on my personal cloud environment, I need to warn you to use it at your own risk!
9 | *
10 | * Setup
11 | * 1. Execute whatsapp-demo.js with `node whatsapp-demo` in parent dir and manually authenticate yourself via your mobile app, qr.png image will be saved
12 | * 2. After authentication, your credentials will be saved to .tmp folder. Get into the folder and zip all the contents to a file named chrome-user.zip
13 | * !! If you are not able to see .tmp folder, you need to reveal hidden files and folders
14 | * 3. Upload your chrome-user.zip file to the default bucket on your Cloud Storage
15 | * !! Be careful if you decide to change storage.rules, make sure this file is securely stored
16 | * 4. Enable Cloud Scheduler and Pub/Sub APIs on your project
17 | * !! https://cloud.google.com/scheduler/docs/quickstart
18 | * 5. Configure crontab for scheduler by using an online generator, like https://crontab.guru/ on L:141-145
19 | * 6. Emulate and deploy your functions with npm scripts emulate & deploy
20 | * !! When emulating, set up admin credentials for local emulation https://firebase.google.com/docs/functions/local-emulator#set_up_admin_credentials_optional and modify path on preemulate script
21 | * !! To enable emulator and run functions locally https: //firebase.google.com/docs/functions/local-emulator
22 | * Tweet me @onderceylan if you've any questions!
23 | */
24 |
25 | const functions = require('firebase-functions');
26 | const puppeteer = require('puppeteer');
27 | const {
28 | getTodaysMessage,
29 | sendMessageToGroup,
30 | listStorageFiles,
31 | downloadUserFile,
32 | unzipUserData,
33 | TEMP_USER_FOLDER_PATH,
34 | USER_FOLDER_NAME } = require('./helpers');
35 |
36 | const GROUP_NAME = 'Bizimkiler';
37 |
38 | sendMessage = async () => {
39 | const todaysMessage = getTodaysMessage();
40 |
41 | // --user-data-dir not as option but as launch arg because https://github.com/puppeteer/puppeteer/issues/921#issuecomment-561054884
42 | // --no-sandbox because fails otherwise with "Running as root without —-no-sandbox is not supported."
43 | const browser = await puppeteer.launch({ headless: true, args: [`--user-data-dir=${TEMP_USER_FOLDER_PATH}`, '--no-sandbox'] });
44 | const page = await browser.newPage();
45 |
46 | try {
47 | await sendMessageToGroup(page, todaysMessage, GROUP_NAME);
48 | } finally {
49 | await page.close();
50 | await browser.close();
51 | }
52 |
53 | return todaysMessage;
54 | };
55 |
56 | executeFunction = async () => {
57 |
58 | const [filesInStorage] = await listStorageFiles();
59 | const userProfileFile = filesInStorage.find(file => file.name.includes(USER_FOLDER_NAME));
60 | const tempFilePath = await downloadUserFile(userProfileFile.name);
61 |
62 | await unzipUserData(tempFilePath);
63 |
64 | return sendMessage();
65 | };
66 |
67 | const scheduleFnAt = (crontab) => functions
68 | // Because function exceeds memory limits when memory is lower than 1GB
69 | .runWith({ timeoutSeconds: 500, memory: '1GB' })
70 | .region('europe-west1')
71 | .pubsub
72 | .schedule(crontab)
73 | .timeZone('Europe/Amsterdam')
74 | .onRun(executeFunction);
75 |
76 | // TODO: find a way to programmatically randomize crontab on Google Cloud scheduler
77 | exports.morningHailOnWeekdays1 = scheduleFnAt('44 7 * * 1');
78 | exports.morningHailOnWeekdays2 = scheduleFnAt('10 8 * * 2');
79 | exports.morningHailOnWeekdays3 = scheduleFnAt('52 7 * * 3');
80 | exports.morningHailOnWeekdays4 = scheduleFnAt('15 8 * * 4');
81 | exports.morningHailOnWeekdays5 = scheduleFnAt('38 8 * * 5');
82 | exports.morningHailOnWeekends1 = scheduleFnAt('44 10 * * 6');
83 | exports.morningHailOnWeekends2 = scheduleFnAt('27 11 * * 0');
84 |
--------------------------------------------------------------------------------
/whatsapp/functions/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "whatsapp-morning-hail",
3 | "requires": true,
4 | "lockfileVersion": 1,
5 | "dependencies": {
6 | "@babel/code-frame": {
7 | "version": "7.5.5",
8 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
9 | "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
10 | "dev": true,
11 | "requires": {
12 | "@babel/highlight": "^7.0.0"
13 | }
14 | },
15 | "@babel/highlight": {
16 | "version": "7.5.0",
17 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz",
18 | "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==",
19 | "dev": true,
20 | "requires": {
21 | "chalk": "^2.0.0",
22 | "esutils": "^2.0.2",
23 | "js-tokens": "^4.0.0"
24 | }
25 | },
26 | "@firebase/app-types": {
27 | "version": "0.6.1",
28 | "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.6.1.tgz",
29 | "integrity": "sha512-L/ZnJRAq7F++utfuoTKX4CLBG5YR7tFO3PLzG1/oXXKEezJ0kRL3CMRoueBEmTCzVb/6SIs2Qlaw++uDgi5Xyg=="
30 | },
31 | "@firebase/auth-interop-types": {
32 | "version": "0.1.5",
33 | "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.5.tgz",
34 | "integrity": "sha512-88h74TMQ6wXChPA6h9Q3E1Jg6TkTHep2+k63OWg3s0ozyGVMeY+TTOti7PFPzq5RhszQPQOoCi59es4MaRvgCw=="
35 | },
36 | "@firebase/component": {
37 | "version": "0.1.19",
38 | "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.19.tgz",
39 | "integrity": "sha512-L0S3g8eqaerg8y0zox3oOHSTwn/FE8RbcRHiurnbESvDViZtP5S5WnhuAPd7FnFxa8ElWK0z1Tr3ikzWDv1xdQ==",
40 | "requires": {
41 | "@firebase/util": "0.3.2",
42 | "tslib": "^1.11.1"
43 | },
44 | "dependencies": {
45 | "tslib": {
46 | "version": "1.14.0",
47 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.0.tgz",
48 | "integrity": "sha512-+Zw5lu0D9tvBMjGP8LpvMb0u2WW2QV3y+D8mO6J+cNzCYIN4sVy43Bf9vl92nqFahutN0I8zHa7cc4vihIshnw=="
49 | }
50 | }
51 | },
52 | "@firebase/database": {
53 | "version": "0.6.13",
54 | "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.13.tgz",
55 | "integrity": "sha512-NommVkAPzU7CKd1gyehmi3lz0K78q0KOfiex7Nfy7MBMwknLm7oNqKovXSgQV1PCLvKXvvAplDSFhDhzIf9obA==",
56 | "requires": {
57 | "@firebase/auth-interop-types": "0.1.5",
58 | "@firebase/component": "0.1.19",
59 | "@firebase/database-types": "0.5.2",
60 | "@firebase/logger": "0.2.6",
61 | "@firebase/util": "0.3.2",
62 | "faye-websocket": "0.11.3",
63 | "tslib": "^1.11.1"
64 | },
65 | "dependencies": {
66 | "tslib": {
67 | "version": "1.14.0",
68 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.0.tgz",
69 | "integrity": "sha512-+Zw5lu0D9tvBMjGP8LpvMb0u2WW2QV3y+D8mO6J+cNzCYIN4sVy43Bf9vl92nqFahutN0I8zHa7cc4vihIshnw=="
70 | }
71 | }
72 | },
73 | "@firebase/database-types": {
74 | "version": "0.5.2",
75 | "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.5.2.tgz",
76 | "integrity": "sha512-ap2WQOS3LKmGuVFKUghFft7RxXTyZTDr0Xd8y2aqmWsbJVjgozi0huL/EUMgTjGFrATAjcf2A7aNs8AKKZ2a8g==",
77 | "requires": {
78 | "@firebase/app-types": "0.6.1"
79 | }
80 | },
81 | "@firebase/logger": {
82 | "version": "0.2.6",
83 | "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz",
84 | "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw=="
85 | },
86 | "@firebase/util": {
87 | "version": "0.3.2",
88 | "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.3.2.tgz",
89 | "integrity": "sha512-Dqs00++c8rwKky6KCKLLY2T1qYO4Q+X5t+lF7DInXDNF4ae1Oau35bkD+OpJ9u7l1pEv7KHowP6CUKuySCOc8g==",
90 | "requires": {
91 | "tslib": "^1.11.1"
92 | },
93 | "dependencies": {
94 | "tslib": {
95 | "version": "1.14.0",
96 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.0.tgz",
97 | "integrity": "sha512-+Zw5lu0D9tvBMjGP8LpvMb0u2WW2QV3y+D8mO6J+cNzCYIN4sVy43Bf9vl92nqFahutN0I8zHa7cc4vihIshnw=="
98 | }
99 | }
100 | },
101 | "@google-cloud/common": {
102 | "version": "3.4.1",
103 | "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-3.4.1.tgz",
104 | "integrity": "sha512-e5z0CwsM0RXky+PnyPtQ3QK46ksqm+kE7kX8pm8X+ddBwZJipHchKeazMM5fLlGCS+AALalzXb+uYmH72TRnpQ==",
105 | "requires": {
106 | "@google-cloud/projectify": "^2.0.0",
107 | "@google-cloud/promisify": "^2.0.0",
108 | "arrify": "^2.0.1",
109 | "duplexify": "^4.1.1",
110 | "ent": "^2.2.0",
111 | "extend": "^3.0.2",
112 | "google-auth-library": "^6.1.1",
113 | "retry-request": "^4.1.1",
114 | "teeny-request": "^7.0.0"
115 | },
116 | "dependencies": {
117 | "duplexify": {
118 | "version": "4.1.1",
119 | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.1.tgz",
120 | "integrity": "sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==",
121 | "requires": {
122 | "end-of-stream": "^1.4.1",
123 | "inherits": "^2.0.3",
124 | "readable-stream": "^3.1.1",
125 | "stream-shift": "^1.0.0"
126 | }
127 | }
128 | }
129 | },
130 | "@google-cloud/firestore": {
131 | "version": "4.4.0",
132 | "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-4.4.0.tgz",
133 | "integrity": "sha512-nixsumd4C7eL+hHEgyihspzhBBNe3agsvNFRX0xfqO3uR/6ro4CUj9XdcCvdnSSd3yTyqKfdBSRK2fEj1jIbYg==",
134 | "optional": true,
135 | "requires": {
136 | "fast-deep-equal": "^3.1.1",
137 | "functional-red-black-tree": "^1.0.1",
138 | "google-gax": "^2.2.0"
139 | },
140 | "dependencies": {
141 | "fast-deep-equal": {
142 | "version": "3.1.3",
143 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
144 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
145 | "optional": true
146 | }
147 | }
148 | },
149 | "@google-cloud/paginator": {
150 | "version": "3.0.5",
151 | "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.5.tgz",
152 | "integrity": "sha512-N4Uk4BT1YuskfRhKXBs0n9Lg2YTROZc6IMpkO/8DIHODtm5s3xY8K5vVBo23v/2XulY3azwITQlYWgT4GdLsUw==",
153 | "requires": {
154 | "arrify": "^2.0.0",
155 | "extend": "^3.0.2"
156 | }
157 | },
158 | "@google-cloud/projectify": {
159 | "version": "2.0.1",
160 | "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.0.1.tgz",
161 | "integrity": "sha512-ZDG38U/Yy6Zr21LaR3BTiiLtpJl6RkPS/JwoRT453G+6Q1DhlV0waNf8Lfu+YVYGIIxgKnLayJRfYlFJfiI8iQ=="
162 | },
163 | "@google-cloud/promisify": {
164 | "version": "2.0.3",
165 | "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.3.tgz",
166 | "integrity": "sha512-d4VSA86eL/AFTe5xtyZX+ePUjE8dIFu2T8zmdeNBSa5/kNgXPCx/o/wbFNHAGLJdGnk1vddRuMESD9HbOC8irw=="
167 | },
168 | "@google-cloud/storage": {
169 | "version": "5.3.0",
170 | "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.3.0.tgz",
171 | "integrity": "sha512-3t5UF3SZ14Bw2kcBHubCai6EIugU2GnQOstYWVSFuoO8IJ94RAaIOPq/dtexvQbUTpBTAGpd5smVR9WPL1mJVw==",
172 | "requires": {
173 | "@google-cloud/common": "^3.3.0",
174 | "@google-cloud/paginator": "^3.0.0",
175 | "@google-cloud/promisify": "^2.0.0",
176 | "arrify": "^2.0.0",
177 | "compressible": "^2.0.12",
178 | "concat-stream": "^2.0.0",
179 | "date-and-time": "^0.14.0",
180 | "duplexify": "^3.5.0",
181 | "extend": "^3.0.2",
182 | "gaxios": "^3.0.0",
183 | "gcs-resumable-upload": "^3.1.0",
184 | "hash-stream-validation": "^0.2.2",
185 | "mime": "^2.2.0",
186 | "mime-types": "^2.0.8",
187 | "onetime": "^5.1.0",
188 | "p-limit": "^3.0.1",
189 | "pumpify": "^2.0.0",
190 | "snakeize": "^0.1.0",
191 | "stream-events": "^1.0.1",
192 | "xdg-basedir": "^4.0.0"
193 | }
194 | },
195 | "@grpc/grpc-js": {
196 | "version": "1.1.8",
197 | "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.1.8.tgz",
198 | "integrity": "sha512-64hg5rmEm6F/NvlWERhHmmgxbWU8nD2TMWE+9TvG7/WcOrFT3fzg/Uu631pXRFwmJ4aWO/kp9vVSlr8FUjBDLA==",
199 | "optional": true,
200 | "requires": {
201 | "@grpc/proto-loader": "^0.6.0-pre14",
202 | "@types/node": "^12.12.47",
203 | "google-auth-library": "^6.0.0",
204 | "semver": "^6.2.0"
205 | },
206 | "dependencies": {
207 | "@grpc/proto-loader": {
208 | "version": "0.6.2",
209 | "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.2.tgz",
210 | "integrity": "sha512-q2Qle60Ht2OQBCp9S5hv1JbI4uBBq6/mqSevFNK3ZEgRDBCAkWqZPUhD/K9gXOHrHKluliHiVq2L9sw1mVyAIg==",
211 | "optional": true,
212 | "requires": {
213 | "@types/long": "^4.0.1",
214 | "lodash.camelcase": "^4.3.0",
215 | "long": "^4.0.0",
216 | "protobufjs": "^6.10.0",
217 | "yargs": "^16.1.1"
218 | }
219 | },
220 | "@types/node": {
221 | "version": "12.20.13",
222 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.13.tgz",
223 | "integrity": "sha512-1x8W5OpxPq+T85OUsHRP6BqXeosKmeXRtjoF39STcdf/UWLqUsoehstZKOi0CunhVqHG17AyZgpj20eRVooK6A==",
224 | "optional": true
225 | },
226 | "ansi-regex": {
227 | "version": "5.0.0",
228 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
229 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
230 | "optional": true
231 | },
232 | "ansi-styles": {
233 | "version": "4.3.0",
234 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
235 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
236 | "optional": true,
237 | "requires": {
238 | "color-convert": "^2.0.1"
239 | }
240 | },
241 | "cliui": {
242 | "version": "7.0.4",
243 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
244 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
245 | "optional": true,
246 | "requires": {
247 | "string-width": "^4.2.0",
248 | "strip-ansi": "^6.0.0",
249 | "wrap-ansi": "^7.0.0"
250 | }
251 | },
252 | "color-convert": {
253 | "version": "2.0.1",
254 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
255 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
256 | "optional": true,
257 | "requires": {
258 | "color-name": "~1.1.4"
259 | }
260 | },
261 | "color-name": {
262 | "version": "1.1.4",
263 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
264 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
265 | "optional": true
266 | },
267 | "emoji-regex": {
268 | "version": "8.0.0",
269 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
270 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
271 | "optional": true
272 | },
273 | "is-fullwidth-code-point": {
274 | "version": "3.0.0",
275 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
276 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
277 | "optional": true
278 | },
279 | "string-width": {
280 | "version": "4.2.2",
281 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
282 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
283 | "optional": true,
284 | "requires": {
285 | "emoji-regex": "^8.0.0",
286 | "is-fullwidth-code-point": "^3.0.0",
287 | "strip-ansi": "^6.0.0"
288 | }
289 | },
290 | "strip-ansi": {
291 | "version": "6.0.0",
292 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
293 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
294 | "optional": true,
295 | "requires": {
296 | "ansi-regex": "^5.0.0"
297 | }
298 | },
299 | "wrap-ansi": {
300 | "version": "7.0.0",
301 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
302 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
303 | "optional": true,
304 | "requires": {
305 | "ansi-styles": "^4.0.0",
306 | "string-width": "^4.1.0",
307 | "strip-ansi": "^6.0.0"
308 | }
309 | },
310 | "y18n": {
311 | "version": "5.0.8",
312 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
313 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
314 | "optional": true
315 | },
316 | "yargs": {
317 | "version": "16.2.0",
318 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
319 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
320 | "optional": true,
321 | "requires": {
322 | "cliui": "^7.0.2",
323 | "escalade": "^3.1.1",
324 | "get-caller-file": "^2.0.5",
325 | "require-directory": "^2.1.1",
326 | "string-width": "^4.2.0",
327 | "y18n": "^5.0.5",
328 | "yargs-parser": "^20.2.2"
329 | }
330 | },
331 | "yargs-parser": {
332 | "version": "20.2.7",
333 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz",
334 | "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==",
335 | "optional": true
336 | }
337 | }
338 | },
339 | "@grpc/proto-loader": {
340 | "version": "0.5.5",
341 | "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.5.tgz",
342 | "integrity": "sha512-WwN9jVNdHRQoOBo9FDH7qU+mgfjPc8GygPYms3M+y3fbQLfnCe/Kv/E01t7JRgnrsOHH8euvSbed3mIalXhwqQ==",
343 | "optional": true,
344 | "requires": {
345 | "lodash.camelcase": "^4.3.0",
346 | "protobufjs": "^6.8.6"
347 | }
348 | },
349 | "@protobufjs/aspromise": {
350 | "version": "1.1.2",
351 | "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
352 | "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=",
353 | "optional": true
354 | },
355 | "@protobufjs/base64": {
356 | "version": "1.1.2",
357 | "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
358 | "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
359 | "optional": true
360 | },
361 | "@protobufjs/codegen": {
362 | "version": "2.0.4",
363 | "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
364 | "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
365 | "optional": true
366 | },
367 | "@protobufjs/eventemitter": {
368 | "version": "1.1.0",
369 | "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
370 | "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=",
371 | "optional": true
372 | },
373 | "@protobufjs/fetch": {
374 | "version": "1.1.0",
375 | "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
376 | "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=",
377 | "optional": true,
378 | "requires": {
379 | "@protobufjs/aspromise": "^1.1.1",
380 | "@protobufjs/inquire": "^1.1.0"
381 | }
382 | },
383 | "@protobufjs/float": {
384 | "version": "1.0.2",
385 | "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
386 | "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=",
387 | "optional": true
388 | },
389 | "@protobufjs/inquire": {
390 | "version": "1.1.0",
391 | "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
392 | "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=",
393 | "optional": true
394 | },
395 | "@protobufjs/path": {
396 | "version": "1.1.2",
397 | "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
398 | "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=",
399 | "optional": true
400 | },
401 | "@protobufjs/pool": {
402 | "version": "1.1.0",
403 | "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
404 | "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=",
405 | "optional": true
406 | },
407 | "@protobufjs/utf8": {
408 | "version": "1.1.0",
409 | "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
410 | "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=",
411 | "optional": true
412 | },
413 | "@tootallnate/once": {
414 | "version": "1.1.2",
415 | "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
416 | "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw=="
417 | },
418 | "@types/body-parser": {
419 | "version": "1.17.1",
420 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.1.tgz",
421 | "integrity": "sha512-RoX2EZjMiFMjZh9lmYrwgoP9RTpAjSHiJxdp4oidAQVO02T7HER3xj9UKue5534ULWeqVEkujhWcyvUce+d68w==",
422 | "requires": {
423 | "@types/connect": "*",
424 | "@types/node": "*"
425 | }
426 | },
427 | "@types/connect": {
428 | "version": "3.4.32",
429 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
430 | "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==",
431 | "requires": {
432 | "@types/node": "*"
433 | }
434 | },
435 | "@types/express": {
436 | "version": "4.17.2",
437 | "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.2.tgz",
438 | "integrity": "sha512-5mHFNyavtLoJmnusB8OKJ5bshSzw+qkMIBAobLrIM48HJvunFva9mOa6aBwh64lBFyNwBbs0xiEFuj4eU/NjCA==",
439 | "requires": {
440 | "@types/body-parser": "*",
441 | "@types/express-serve-static-core": "*",
442 | "@types/serve-static": "*"
443 | }
444 | },
445 | "@types/express-serve-static-core": {
446 | "version": "4.17.0",
447 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.0.tgz",
448 | "integrity": "sha512-Xnub7w57uvcBqFdIGoRg1KhNOeEj0vB6ykUM7uFWyxvbdE89GFyqgmUcanAriMr4YOxNFZBAWkfcWIb4WBPt3g==",
449 | "requires": {
450 | "@types/node": "*",
451 | "@types/range-parser": "*"
452 | }
453 | },
454 | "@types/lodash": {
455 | "version": "4.14.149",
456 | "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz",
457 | "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==",
458 | "dev": true
459 | },
460 | "@types/long": {
461 | "version": "4.0.1",
462 | "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz",
463 | "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==",
464 | "optional": true
465 | },
466 | "@types/mime": {
467 | "version": "2.0.1",
468 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz",
469 | "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw=="
470 | },
471 | "@types/node": {
472 | "version": "8.10.59",
473 | "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.59.tgz",
474 | "integrity": "sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ=="
475 | },
476 | "@types/range-parser": {
477 | "version": "1.2.3",
478 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
479 | "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
480 | },
481 | "@types/serve-static": {
482 | "version": "1.13.3",
483 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz",
484 | "integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==",
485 | "requires": {
486 | "@types/express-serve-static-core": "*",
487 | "@types/mime": "*"
488 | }
489 | },
490 | "abort-controller": {
491 | "version": "3.0.0",
492 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
493 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
494 | "requires": {
495 | "event-target-shim": "^5.0.0"
496 | }
497 | },
498 | "accepts": {
499 | "version": "1.3.7",
500 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
501 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
502 | "requires": {
503 | "mime-types": "~2.1.24",
504 | "negotiator": "0.6.2"
505 | }
506 | },
507 | "acorn": {
508 | "version": "6.4.1",
509 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
510 | "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
511 | "dev": true
512 | },
513 | "acorn-jsx": {
514 | "version": "5.1.0",
515 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz",
516 | "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==",
517 | "dev": true
518 | },
519 | "agent-base": {
520 | "version": "4.3.0",
521 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
522 | "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
523 | "requires": {
524 | "es6-promisify": "^5.0.0"
525 | }
526 | },
527 | "ajv": {
528 | "version": "6.10.2",
529 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
530 | "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
531 | "dev": true,
532 | "requires": {
533 | "fast-deep-equal": "^2.0.1",
534 | "fast-json-stable-stringify": "^2.0.0",
535 | "json-schema-traverse": "^0.4.1",
536 | "uri-js": "^4.2.2"
537 | }
538 | },
539 | "ansi-escapes": {
540 | "version": "3.2.0",
541 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
542 | "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
543 | "dev": true
544 | },
545 | "ansi-regex": {
546 | "version": "3.0.0",
547 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
548 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
549 | "dev": true
550 | },
551 | "ansi-styles": {
552 | "version": "3.2.1",
553 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
554 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
555 | "dev": true,
556 | "requires": {
557 | "color-convert": "^1.9.0"
558 | }
559 | },
560 | "argparse": {
561 | "version": "1.0.10",
562 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
563 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
564 | "dev": true,
565 | "requires": {
566 | "sprintf-js": "~1.0.2"
567 | }
568 | },
569 | "array-flatten": {
570 | "version": "1.1.1",
571 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
572 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
573 | },
574 | "arrify": {
575 | "version": "2.0.1",
576 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
577 | "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug=="
578 | },
579 | "astral-regex": {
580 | "version": "1.0.0",
581 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
582 | "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
583 | "dev": true
584 | },
585 | "async-limiter": {
586 | "version": "1.0.1",
587 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
588 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
589 | },
590 | "balanced-match": {
591 | "version": "1.0.0",
592 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
593 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
594 | },
595 | "base64-js": {
596 | "version": "1.3.1",
597 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
598 | "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
599 | },
600 | "big-integer": {
601 | "version": "1.6.48",
602 | "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
603 | "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w=="
604 | },
605 | "bignumber.js": {
606 | "version": "9.0.1",
607 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz",
608 | "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA=="
609 | },
610 | "binary": {
611 | "version": "0.3.0",
612 | "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz",
613 | "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=",
614 | "requires": {
615 | "buffers": "~0.1.1",
616 | "chainsaw": "~0.1.0"
617 | }
618 | },
619 | "bluebird": {
620 | "version": "3.4.7",
621 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
622 | "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM="
623 | },
624 | "body-parser": {
625 | "version": "1.19.0",
626 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
627 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
628 | "requires": {
629 | "bytes": "3.1.0",
630 | "content-type": "~1.0.4",
631 | "debug": "2.6.9",
632 | "depd": "~1.1.2",
633 | "http-errors": "1.7.2",
634 | "iconv-lite": "0.4.24",
635 | "on-finished": "~2.3.0",
636 | "qs": "6.7.0",
637 | "raw-body": "2.4.0",
638 | "type-is": "~1.6.17"
639 | },
640 | "dependencies": {
641 | "debug": {
642 | "version": "2.6.9",
643 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
644 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
645 | "requires": {
646 | "ms": "2.0.0"
647 | }
648 | },
649 | "ms": {
650 | "version": "2.0.0",
651 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
652 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
653 | }
654 | }
655 | },
656 | "brace-expansion": {
657 | "version": "1.1.11",
658 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
659 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
660 | "requires": {
661 | "balanced-match": "^1.0.0",
662 | "concat-map": "0.0.1"
663 | }
664 | },
665 | "buffer-crc32": {
666 | "version": "0.2.13",
667 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
668 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
669 | },
670 | "buffer-equal-constant-time": {
671 | "version": "1.0.1",
672 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
673 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
674 | },
675 | "buffer-from": {
676 | "version": "1.1.1",
677 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
678 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
679 | },
680 | "buffer-indexof-polyfill": {
681 | "version": "1.0.1",
682 | "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.1.tgz",
683 | "integrity": "sha1-qfuAbOgUXVQoUQznLyeLs2OmOL8="
684 | },
685 | "buffers": {
686 | "version": "0.1.1",
687 | "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz",
688 | "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s="
689 | },
690 | "bytes": {
691 | "version": "3.1.0",
692 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
693 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
694 | },
695 | "callsites": {
696 | "version": "3.1.0",
697 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
698 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
699 | "dev": true
700 | },
701 | "chainsaw": {
702 | "version": "0.1.0",
703 | "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
704 | "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=",
705 | "requires": {
706 | "traverse": ">=0.3.0 <0.4"
707 | }
708 | },
709 | "chalk": {
710 | "version": "2.4.2",
711 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
712 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
713 | "dev": true,
714 | "requires": {
715 | "ansi-styles": "^3.2.1",
716 | "escape-string-regexp": "^1.0.5",
717 | "supports-color": "^5.3.0"
718 | }
719 | },
720 | "chardet": {
721 | "version": "0.7.0",
722 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
723 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
724 | "dev": true
725 | },
726 | "cli-cursor": {
727 | "version": "2.1.0",
728 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
729 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
730 | "dev": true,
731 | "requires": {
732 | "restore-cursor": "^2.0.0"
733 | }
734 | },
735 | "cli-width": {
736 | "version": "2.2.0",
737 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
738 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
739 | "dev": true
740 | },
741 | "color-convert": {
742 | "version": "1.9.3",
743 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
744 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
745 | "dev": true,
746 | "requires": {
747 | "color-name": "1.1.3"
748 | }
749 | },
750 | "color-name": {
751 | "version": "1.1.3",
752 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
753 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
754 | "dev": true
755 | },
756 | "compressible": {
757 | "version": "2.0.18",
758 | "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
759 | "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
760 | "requires": {
761 | "mime-db": ">= 1.43.0 < 2"
762 | },
763 | "dependencies": {
764 | "mime-db": {
765 | "version": "1.45.0",
766 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz",
767 | "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w=="
768 | }
769 | }
770 | },
771 | "concat-map": {
772 | "version": "0.0.1",
773 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
774 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
775 | },
776 | "concat-stream": {
777 | "version": "2.0.0",
778 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
779 | "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
780 | "requires": {
781 | "buffer-from": "^1.0.0",
782 | "inherits": "^2.0.3",
783 | "readable-stream": "^3.0.2",
784 | "typedarray": "^0.0.6"
785 | }
786 | },
787 | "configstore": {
788 | "version": "5.0.1",
789 | "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz",
790 | "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==",
791 | "requires": {
792 | "dot-prop": "^5.2.0",
793 | "graceful-fs": "^4.1.2",
794 | "make-dir": "^3.0.0",
795 | "unique-string": "^2.0.0",
796 | "write-file-atomic": "^3.0.0",
797 | "xdg-basedir": "^4.0.0"
798 | }
799 | },
800 | "content-disposition": {
801 | "version": "0.5.3",
802 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
803 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
804 | "requires": {
805 | "safe-buffer": "5.1.2"
806 | }
807 | },
808 | "content-type": {
809 | "version": "1.0.4",
810 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
811 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
812 | },
813 | "cookie": {
814 | "version": "0.4.0",
815 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
816 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
817 | },
818 | "cookie-signature": {
819 | "version": "1.0.6",
820 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
821 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
822 | },
823 | "core-util-is": {
824 | "version": "1.0.2",
825 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
826 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
827 | },
828 | "cors": {
829 | "version": "2.8.5",
830 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
831 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
832 | "requires": {
833 | "object-assign": "^4",
834 | "vary": "^1"
835 | }
836 | },
837 | "cross-spawn": {
838 | "version": "6.0.5",
839 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
840 | "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
841 | "dev": true,
842 | "requires": {
843 | "nice-try": "^1.0.4",
844 | "path-key": "^2.0.1",
845 | "semver": "^5.5.0",
846 | "shebang-command": "^1.2.0",
847 | "which": "^1.2.9"
848 | },
849 | "dependencies": {
850 | "semver": {
851 | "version": "5.7.1",
852 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
853 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
854 | "dev": true
855 | }
856 | }
857 | },
858 | "crypto-random-string": {
859 | "version": "2.0.0",
860 | "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
861 | "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA=="
862 | },
863 | "date-and-time": {
864 | "version": "0.14.2",
865 | "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-0.14.2.tgz",
866 | "integrity": "sha512-EFTCh9zRSEpGPmJaexg7HTuzZHh6cnJj1ui7IGCFNXzd2QdpsNh05Db5TF3xzJm30YN+A8/6xHSuRcQqoc3kFA=="
867 | },
868 | "debug": {
869 | "version": "3.2.6",
870 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
871 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
872 | "requires": {
873 | "ms": "^2.1.1"
874 | }
875 | },
876 | "deep-is": {
877 | "version": "0.1.3",
878 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
879 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
880 | "dev": true
881 | },
882 | "depd": {
883 | "version": "1.1.2",
884 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
885 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
886 | },
887 | "destroy": {
888 | "version": "1.0.4",
889 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
890 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
891 | },
892 | "dicer": {
893 | "version": "0.3.0",
894 | "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz",
895 | "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==",
896 | "requires": {
897 | "streamsearch": "0.1.2"
898 | }
899 | },
900 | "doctrine": {
901 | "version": "3.0.0",
902 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
903 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
904 | "dev": true,
905 | "requires": {
906 | "esutils": "^2.0.2"
907 | }
908 | },
909 | "dot-prop": {
910 | "version": "5.3.0",
911 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
912 | "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
913 | "requires": {
914 | "is-obj": "^2.0.0"
915 | }
916 | },
917 | "duplexer2": {
918 | "version": "0.1.4",
919 | "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
920 | "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=",
921 | "requires": {
922 | "readable-stream": "^2.0.2"
923 | },
924 | "dependencies": {
925 | "readable-stream": {
926 | "version": "2.3.7",
927 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
928 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
929 | "requires": {
930 | "core-util-is": "~1.0.0",
931 | "inherits": "~2.0.3",
932 | "isarray": "~1.0.0",
933 | "process-nextick-args": "~2.0.0",
934 | "safe-buffer": "~5.1.1",
935 | "string_decoder": "~1.1.1",
936 | "util-deprecate": "~1.0.1"
937 | }
938 | }
939 | }
940 | },
941 | "duplexify": {
942 | "version": "3.7.1",
943 | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
944 | "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
945 | "requires": {
946 | "end-of-stream": "^1.0.0",
947 | "inherits": "^2.0.1",
948 | "readable-stream": "^2.0.0",
949 | "stream-shift": "^1.0.0"
950 | },
951 | "dependencies": {
952 | "readable-stream": {
953 | "version": "2.3.7",
954 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
955 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
956 | "requires": {
957 | "core-util-is": "~1.0.0",
958 | "inherits": "~2.0.3",
959 | "isarray": "~1.0.0",
960 | "process-nextick-args": "~2.0.0",
961 | "safe-buffer": "~5.1.1",
962 | "string_decoder": "~1.1.1",
963 | "util-deprecate": "~1.0.1"
964 | }
965 | }
966 | }
967 | },
968 | "ecdsa-sig-formatter": {
969 | "version": "1.0.11",
970 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
971 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
972 | "requires": {
973 | "safe-buffer": "^5.0.1"
974 | }
975 | },
976 | "ee-first": {
977 | "version": "1.1.1",
978 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
979 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
980 | },
981 | "emoji-regex": {
982 | "version": "7.0.3",
983 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
984 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
985 | "dev": true
986 | },
987 | "encodeurl": {
988 | "version": "1.0.2",
989 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
990 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
991 | },
992 | "end-of-stream": {
993 | "version": "1.4.4",
994 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
995 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
996 | "requires": {
997 | "once": "^1.4.0"
998 | }
999 | },
1000 | "ent": {
1001 | "version": "2.2.0",
1002 | "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz",
1003 | "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0="
1004 | },
1005 | "es6-promise": {
1006 | "version": "4.2.8",
1007 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
1008 | "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
1009 | },
1010 | "es6-promisify": {
1011 | "version": "5.0.0",
1012 | "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
1013 | "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
1014 | "requires": {
1015 | "es6-promise": "^4.0.3"
1016 | }
1017 | },
1018 | "escalade": {
1019 | "version": "3.1.1",
1020 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
1021 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
1022 | "optional": true
1023 | },
1024 | "escape-html": {
1025 | "version": "1.0.3",
1026 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
1027 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
1028 | },
1029 | "escape-string-regexp": {
1030 | "version": "1.0.5",
1031 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
1032 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
1033 | "dev": true
1034 | },
1035 | "eslint": {
1036 | "version": "5.16.0",
1037 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz",
1038 | "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==",
1039 | "dev": true,
1040 | "requires": {
1041 | "@babel/code-frame": "^7.0.0",
1042 | "ajv": "^6.9.1",
1043 | "chalk": "^2.1.0",
1044 | "cross-spawn": "^6.0.5",
1045 | "debug": "^4.0.1",
1046 | "doctrine": "^3.0.0",
1047 | "eslint-scope": "^4.0.3",
1048 | "eslint-utils": "^1.3.1",
1049 | "eslint-visitor-keys": "^1.0.0",
1050 | "espree": "^5.0.1",
1051 | "esquery": "^1.0.1",
1052 | "esutils": "^2.0.2",
1053 | "file-entry-cache": "^5.0.1",
1054 | "functional-red-black-tree": "^1.0.1",
1055 | "glob": "^7.1.2",
1056 | "globals": "^11.7.0",
1057 | "ignore": "^4.0.6",
1058 | "import-fresh": "^3.0.0",
1059 | "imurmurhash": "^0.1.4",
1060 | "inquirer": "^6.2.2",
1061 | "js-yaml": "^3.13.0",
1062 | "json-stable-stringify-without-jsonify": "^1.0.1",
1063 | "levn": "^0.3.0",
1064 | "lodash": "^4.17.11",
1065 | "minimatch": "^3.0.4",
1066 | "mkdirp": "^0.5.1",
1067 | "natural-compare": "^1.4.0",
1068 | "optionator": "^0.8.2",
1069 | "path-is-inside": "^1.0.2",
1070 | "progress": "^2.0.0",
1071 | "regexpp": "^2.0.1",
1072 | "semver": "^5.5.1",
1073 | "strip-ansi": "^4.0.0",
1074 | "strip-json-comments": "^2.0.1",
1075 | "table": "^5.2.3",
1076 | "text-table": "^0.2.0"
1077 | },
1078 | "dependencies": {
1079 | "debug": {
1080 | "version": "4.1.1",
1081 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
1082 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
1083 | "dev": true,
1084 | "requires": {
1085 | "ms": "^2.1.1"
1086 | }
1087 | },
1088 | "semver": {
1089 | "version": "5.7.1",
1090 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
1091 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
1092 | "dev": true
1093 | }
1094 | }
1095 | },
1096 | "eslint-plugin-promise": {
1097 | "version": "4.2.1",
1098 | "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz",
1099 | "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==",
1100 | "dev": true
1101 | },
1102 | "eslint-scope": {
1103 | "version": "4.0.3",
1104 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
1105 | "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
1106 | "dev": true,
1107 | "requires": {
1108 | "esrecurse": "^4.1.0",
1109 | "estraverse": "^4.1.1"
1110 | }
1111 | },
1112 | "eslint-utils": {
1113 | "version": "1.4.3",
1114 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
1115 | "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
1116 | "dev": true,
1117 | "requires": {
1118 | "eslint-visitor-keys": "^1.1.0"
1119 | }
1120 | },
1121 | "eslint-visitor-keys": {
1122 | "version": "1.1.0",
1123 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
1124 | "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
1125 | "dev": true
1126 | },
1127 | "espree": {
1128 | "version": "5.0.1",
1129 | "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz",
1130 | "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==",
1131 | "dev": true,
1132 | "requires": {
1133 | "acorn": "^6.0.7",
1134 | "acorn-jsx": "^5.0.0",
1135 | "eslint-visitor-keys": "^1.0.0"
1136 | }
1137 | },
1138 | "esprima": {
1139 | "version": "4.0.1",
1140 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
1141 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
1142 | "dev": true
1143 | },
1144 | "esquery": {
1145 | "version": "1.0.1",
1146 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
1147 | "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
1148 | "dev": true,
1149 | "requires": {
1150 | "estraverse": "^4.0.0"
1151 | }
1152 | },
1153 | "esrecurse": {
1154 | "version": "4.2.1",
1155 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
1156 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
1157 | "dev": true,
1158 | "requires": {
1159 | "estraverse": "^4.1.0"
1160 | }
1161 | },
1162 | "estraverse": {
1163 | "version": "4.3.0",
1164 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
1165 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
1166 | "dev": true
1167 | },
1168 | "esutils": {
1169 | "version": "2.0.3",
1170 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
1171 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
1172 | "dev": true
1173 | },
1174 | "etag": {
1175 | "version": "1.8.1",
1176 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
1177 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
1178 | },
1179 | "event-target-shim": {
1180 | "version": "5.0.1",
1181 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
1182 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
1183 | },
1184 | "express": {
1185 | "version": "4.17.1",
1186 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
1187 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
1188 | "requires": {
1189 | "accepts": "~1.3.7",
1190 | "array-flatten": "1.1.1",
1191 | "body-parser": "1.19.0",
1192 | "content-disposition": "0.5.3",
1193 | "content-type": "~1.0.4",
1194 | "cookie": "0.4.0",
1195 | "cookie-signature": "1.0.6",
1196 | "debug": "2.6.9",
1197 | "depd": "~1.1.2",
1198 | "encodeurl": "~1.0.2",
1199 | "escape-html": "~1.0.3",
1200 | "etag": "~1.8.1",
1201 | "finalhandler": "~1.1.2",
1202 | "fresh": "0.5.2",
1203 | "merge-descriptors": "1.0.1",
1204 | "methods": "~1.1.2",
1205 | "on-finished": "~2.3.0",
1206 | "parseurl": "~1.3.3",
1207 | "path-to-regexp": "0.1.7",
1208 | "proxy-addr": "~2.0.5",
1209 | "qs": "6.7.0",
1210 | "range-parser": "~1.2.1",
1211 | "safe-buffer": "5.1.2",
1212 | "send": "0.17.1",
1213 | "serve-static": "1.14.1",
1214 | "setprototypeof": "1.1.1",
1215 | "statuses": "~1.5.0",
1216 | "type-is": "~1.6.18",
1217 | "utils-merge": "1.0.1",
1218 | "vary": "~1.1.2"
1219 | },
1220 | "dependencies": {
1221 | "debug": {
1222 | "version": "2.6.9",
1223 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
1224 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
1225 | "requires": {
1226 | "ms": "2.0.0"
1227 | }
1228 | },
1229 | "ms": {
1230 | "version": "2.0.0",
1231 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1232 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
1233 | }
1234 | }
1235 | },
1236 | "extend": {
1237 | "version": "3.0.2",
1238 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
1239 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
1240 | },
1241 | "external-editor": {
1242 | "version": "3.1.0",
1243 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
1244 | "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
1245 | "dev": true,
1246 | "requires": {
1247 | "chardet": "^0.7.0",
1248 | "iconv-lite": "^0.4.24",
1249 | "tmp": "^0.0.33"
1250 | }
1251 | },
1252 | "extract-zip": {
1253 | "version": "1.7.0",
1254 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz",
1255 | "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==",
1256 | "requires": {
1257 | "concat-stream": "^1.6.2",
1258 | "debug": "^2.6.9",
1259 | "mkdirp": "^0.5.4",
1260 | "yauzl": "^2.10.0"
1261 | },
1262 | "dependencies": {
1263 | "concat-stream": {
1264 | "version": "1.6.2",
1265 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
1266 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
1267 | "requires": {
1268 | "buffer-from": "^1.0.0",
1269 | "inherits": "^2.0.3",
1270 | "readable-stream": "^2.2.2",
1271 | "typedarray": "^0.0.6"
1272 | }
1273 | },
1274 | "debug": {
1275 | "version": "2.6.9",
1276 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
1277 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
1278 | "requires": {
1279 | "ms": "2.0.0"
1280 | }
1281 | },
1282 | "ms": {
1283 | "version": "2.0.0",
1284 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1285 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
1286 | },
1287 | "readable-stream": {
1288 | "version": "2.3.7",
1289 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
1290 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
1291 | "requires": {
1292 | "core-util-is": "~1.0.0",
1293 | "inherits": "~2.0.3",
1294 | "isarray": "~1.0.0",
1295 | "process-nextick-args": "~2.0.0",
1296 | "safe-buffer": "~5.1.1",
1297 | "string_decoder": "~1.1.1",
1298 | "util-deprecate": "~1.0.1"
1299 | }
1300 | }
1301 | }
1302 | },
1303 | "fast-deep-equal": {
1304 | "version": "2.0.1",
1305 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
1306 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
1307 | "dev": true
1308 | },
1309 | "fast-json-stable-stringify": {
1310 | "version": "2.0.0",
1311 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
1312 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
1313 | "dev": true
1314 | },
1315 | "fast-levenshtein": {
1316 | "version": "2.0.6",
1317 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
1318 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
1319 | "dev": true
1320 | },
1321 | "fast-text-encoding": {
1322 | "version": "1.0.3",
1323 | "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz",
1324 | "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig=="
1325 | },
1326 | "faye-websocket": {
1327 | "version": "0.11.3",
1328 | "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz",
1329 | "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==",
1330 | "requires": {
1331 | "websocket-driver": ">=0.5.1"
1332 | }
1333 | },
1334 | "fd-slicer": {
1335 | "version": "1.1.0",
1336 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
1337 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
1338 | "requires": {
1339 | "pend": "~1.2.0"
1340 | }
1341 | },
1342 | "figures": {
1343 | "version": "2.0.0",
1344 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
1345 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
1346 | "dev": true,
1347 | "requires": {
1348 | "escape-string-regexp": "^1.0.5"
1349 | }
1350 | },
1351 | "file-entry-cache": {
1352 | "version": "5.0.1",
1353 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
1354 | "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
1355 | "dev": true,
1356 | "requires": {
1357 | "flat-cache": "^2.0.1"
1358 | }
1359 | },
1360 | "finalhandler": {
1361 | "version": "1.1.2",
1362 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
1363 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
1364 | "requires": {
1365 | "debug": "2.6.9",
1366 | "encodeurl": "~1.0.2",
1367 | "escape-html": "~1.0.3",
1368 | "on-finished": "~2.3.0",
1369 | "parseurl": "~1.3.3",
1370 | "statuses": "~1.5.0",
1371 | "unpipe": "~1.0.0"
1372 | },
1373 | "dependencies": {
1374 | "debug": {
1375 | "version": "2.6.9",
1376 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
1377 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
1378 | "requires": {
1379 | "ms": "2.0.0"
1380 | }
1381 | },
1382 | "ms": {
1383 | "version": "2.0.0",
1384 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1385 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
1386 | }
1387 | }
1388 | },
1389 | "firebase-admin": {
1390 | "version": "9.2.0",
1391 | "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-9.2.0.tgz",
1392 | "integrity": "sha512-LhnMYl71B4gP1FlTLfwaYlOWhBCAcNF+byb2CPTfaW/T4hkp4qlXOgo2bws/zbAv5X9GTFqGir3KexMslVGsIA==",
1393 | "requires": {
1394 | "@firebase/database": "^0.6.10",
1395 | "@firebase/database-types": "^0.5.2",
1396 | "@google-cloud/firestore": "^4.0.0",
1397 | "@google-cloud/storage": "^5.3.0",
1398 | "@types/node": "^10.10.0",
1399 | "dicer": "^0.3.0",
1400 | "jsonwebtoken": "^8.5.1",
1401 | "node-forge": "^0.10.0"
1402 | },
1403 | "dependencies": {
1404 | "@types/node": {
1405 | "version": "10.17.37",
1406 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.37.tgz",
1407 | "integrity": "sha512-4c38N7p9k9yqdcANh/WExTahkBgOTmggCyrTvVcbE8ByqO3g8evt/407v/I4X/gdfUkIyZBSQh/Rc3tvuwlVGw=="
1408 | }
1409 | }
1410 | },
1411 | "firebase-functions": {
1412 | "version": "3.3.0",
1413 | "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-3.3.0.tgz",
1414 | "integrity": "sha512-dP6PCG+OwR6RtFpOqwPsLnfiCr3CwXAm/SVGMbO53vDAk0nhUQ1WGAyHDYmIyMAkaLJkIKGwDnX7XmZ5+yAg7g==",
1415 | "requires": {
1416 | "@types/express": "^4.17.0",
1417 | "cors": "^2.8.5",
1418 | "express": "^4.17.1",
1419 | "jsonwebtoken": "^8.5.1",
1420 | "lodash": "^4.17.14"
1421 | },
1422 | "dependencies": {
1423 | "jsonwebtoken": {
1424 | "version": "8.5.1",
1425 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
1426 | "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
1427 | "requires": {
1428 | "jws": "^3.2.2",
1429 | "lodash.includes": "^4.3.0",
1430 | "lodash.isboolean": "^3.0.3",
1431 | "lodash.isinteger": "^4.0.4",
1432 | "lodash.isnumber": "^3.0.3",
1433 | "lodash.isplainobject": "^4.0.6",
1434 | "lodash.isstring": "^4.0.1",
1435 | "lodash.once": "^4.0.0",
1436 | "ms": "^2.1.1",
1437 | "semver": "^5.6.0"
1438 | }
1439 | },
1440 | "semver": {
1441 | "version": "5.7.1",
1442 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
1443 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
1444 | }
1445 | }
1446 | },
1447 | "firebase-functions-test": {
1448 | "version": "0.1.7",
1449 | "resolved": "https://registry.npmjs.org/firebase-functions-test/-/firebase-functions-test-0.1.7.tgz",
1450 | "integrity": "sha512-/zVQhaUZ+M7z25aUaZSIah0MIDZIfnRfQxtHYTE8hgUgODmKdaMX20vh5Gv23hnCPauIHuYb7XFTUOZiWU1udA==",
1451 | "dev": true,
1452 | "requires": {
1453 | "@types/lodash": "^4.14.104",
1454 | "lodash": "^4.17.5"
1455 | }
1456 | },
1457 | "flat-cache": {
1458 | "version": "2.0.1",
1459 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
1460 | "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
1461 | "dev": true,
1462 | "requires": {
1463 | "flatted": "^2.0.0",
1464 | "rimraf": "2.6.3",
1465 | "write": "1.0.3"
1466 | },
1467 | "dependencies": {
1468 | "rimraf": {
1469 | "version": "2.6.3",
1470 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
1471 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
1472 | "dev": true,
1473 | "requires": {
1474 | "glob": "^7.1.3"
1475 | }
1476 | }
1477 | }
1478 | },
1479 | "flatted": {
1480 | "version": "2.0.1",
1481 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
1482 | "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
1483 | "dev": true
1484 | },
1485 | "forwarded": {
1486 | "version": "0.1.2",
1487 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
1488 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
1489 | },
1490 | "fresh": {
1491 | "version": "0.5.2",
1492 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
1493 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
1494 | },
1495 | "fs.realpath": {
1496 | "version": "1.0.0",
1497 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
1498 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
1499 | },
1500 | "fstream": {
1501 | "version": "1.0.12",
1502 | "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
1503 | "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
1504 | "requires": {
1505 | "graceful-fs": "^4.1.2",
1506 | "inherits": "~2.0.0",
1507 | "mkdirp": ">=0.5 0",
1508 | "rimraf": "2"
1509 | }
1510 | },
1511 | "functional-red-black-tree": {
1512 | "version": "1.0.1",
1513 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
1514 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
1515 | },
1516 | "gaxios": {
1517 | "version": "3.2.0",
1518 | "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.2.0.tgz",
1519 | "integrity": "sha512-+6WPeVzPvOshftpxJwRi2Ozez80tn/hdtOUag7+gajDHRJvAblKxTFSSMPtr2hmnLy7p0mvYz0rMXLBl8pSO7Q==",
1520 | "requires": {
1521 | "abort-controller": "^3.0.0",
1522 | "extend": "^3.0.2",
1523 | "https-proxy-agent": "^5.0.0",
1524 | "is-stream": "^2.0.0",
1525 | "node-fetch": "^2.3.0"
1526 | },
1527 | "dependencies": {
1528 | "agent-base": {
1529 | "version": "6.0.1",
1530 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz",
1531 | "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==",
1532 | "requires": {
1533 | "debug": "4"
1534 | }
1535 | },
1536 | "debug": {
1537 | "version": "4.2.0",
1538 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
1539 | "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
1540 | "requires": {
1541 | "ms": "2.1.2"
1542 | }
1543 | },
1544 | "https-proxy-agent": {
1545 | "version": "5.0.0",
1546 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
1547 | "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
1548 | "requires": {
1549 | "agent-base": "6",
1550 | "debug": "4"
1551 | }
1552 | }
1553 | }
1554 | },
1555 | "gcp-metadata": {
1556 | "version": "4.2.0",
1557 | "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.2.0.tgz",
1558 | "integrity": "sha512-vQZD57cQkqIA6YPGXM/zc+PIZfNRFdukWGsGZ5+LcJzesi5xp6Gn7a02wRJi4eXPyArNMIYpPET4QMxGqtlk6Q==",
1559 | "requires": {
1560 | "gaxios": "^3.0.0",
1561 | "json-bigint": "^1.0.0"
1562 | }
1563 | },
1564 | "gcs-resumable-upload": {
1565 | "version": "3.1.1",
1566 | "resolved": "https://registry.npmjs.org/gcs-resumable-upload/-/gcs-resumable-upload-3.1.1.tgz",
1567 | "integrity": "sha512-RS1osvAicj9+MjCc6jAcVL1Pt3tg7NK2C2gXM5nqD1Gs0klF2kj5nnAFSBy97JrtslMIQzpb7iSuxaG8rFWd2A==",
1568 | "requires": {
1569 | "abort-controller": "^3.0.0",
1570 | "configstore": "^5.0.0",
1571 | "extend": "^3.0.2",
1572 | "gaxios": "^3.0.0",
1573 | "google-auth-library": "^6.0.0",
1574 | "pumpify": "^2.0.0",
1575 | "stream-events": "^1.0.4"
1576 | }
1577 | },
1578 | "get-caller-file": {
1579 | "version": "2.0.5",
1580 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
1581 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
1582 | "optional": true
1583 | },
1584 | "glob": {
1585 | "version": "7.1.6",
1586 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
1587 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
1588 | "requires": {
1589 | "fs.realpath": "^1.0.0",
1590 | "inflight": "^1.0.4",
1591 | "inherits": "2",
1592 | "minimatch": "^3.0.4",
1593 | "once": "^1.3.0",
1594 | "path-is-absolute": "^1.0.0"
1595 | }
1596 | },
1597 | "globals": {
1598 | "version": "11.12.0",
1599 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
1600 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
1601 | "dev": true
1602 | },
1603 | "google-auth-library": {
1604 | "version": "6.1.1",
1605 | "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.1.tgz",
1606 | "integrity": "sha512-0WfExOx3FrLYnY88RICQxvpaNzdwjz44OsHqHkIoAJfjY6Jck6CZRl1ASWadk+wbJ0LhkQ8rNY4zZebKml4Ghg==",
1607 | "requires": {
1608 | "arrify": "^2.0.0",
1609 | "base64-js": "^1.3.0",
1610 | "ecdsa-sig-formatter": "^1.0.11",
1611 | "fast-text-encoding": "^1.0.0",
1612 | "gaxios": "^3.0.0",
1613 | "gcp-metadata": "^4.1.0",
1614 | "gtoken": "^5.0.4",
1615 | "jws": "^4.0.0",
1616 | "lru-cache": "^6.0.0"
1617 | },
1618 | "dependencies": {
1619 | "jwa": {
1620 | "version": "2.0.0",
1621 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
1622 | "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
1623 | "requires": {
1624 | "buffer-equal-constant-time": "1.0.1",
1625 | "ecdsa-sig-formatter": "1.0.11",
1626 | "safe-buffer": "^5.0.1"
1627 | }
1628 | },
1629 | "jws": {
1630 | "version": "4.0.0",
1631 | "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
1632 | "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
1633 | "requires": {
1634 | "jwa": "^2.0.0",
1635 | "safe-buffer": "^5.0.1"
1636 | }
1637 | }
1638 | }
1639 | },
1640 | "google-gax": {
1641 | "version": "2.9.0",
1642 | "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-2.9.0.tgz",
1643 | "integrity": "sha512-MFMwA7Fb8PEwjnYwfGXjZMidCNyMl3gSnvS/+kS8TQioJZQDpzK+W3dmwyNyig/U13+kbABqDnbkkAXJ5NiUkw==",
1644 | "optional": true,
1645 | "requires": {
1646 | "@grpc/grpc-js": "~1.1.1",
1647 | "@grpc/proto-loader": "^0.5.1",
1648 | "@types/long": "^4.0.0",
1649 | "abort-controller": "^3.0.0",
1650 | "duplexify": "^4.0.0",
1651 | "google-auth-library": "^6.0.0",
1652 | "is-stream-ended": "^0.1.4",
1653 | "node-fetch": "^2.6.1",
1654 | "protobufjs": "^6.9.0",
1655 | "retry-request": "^4.0.0"
1656 | },
1657 | "dependencies": {
1658 | "duplexify": {
1659 | "version": "4.1.1",
1660 | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.1.tgz",
1661 | "integrity": "sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==",
1662 | "optional": true,
1663 | "requires": {
1664 | "end-of-stream": "^1.4.1",
1665 | "inherits": "^2.0.3",
1666 | "readable-stream": "^3.1.1",
1667 | "stream-shift": "^1.0.0"
1668 | }
1669 | }
1670 | }
1671 | },
1672 | "google-p12-pem": {
1673 | "version": "3.0.3",
1674 | "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz",
1675 | "integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==",
1676 | "requires": {
1677 | "node-forge": "^0.10.0"
1678 | }
1679 | },
1680 | "graceful-fs": {
1681 | "version": "4.2.3",
1682 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
1683 | "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ=="
1684 | },
1685 | "gtoken": {
1686 | "version": "5.0.4",
1687 | "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.0.4.tgz",
1688 | "integrity": "sha512-U9wnSp4GZ7ov6zRdPuRHG4TuqEWqRRgT1gfXGNArhzBUn9byrPeH8uTmBWU/ZiWJJvTEmkjhDIC3mqHWdVi3xQ==",
1689 | "requires": {
1690 | "gaxios": "^3.0.0",
1691 | "google-p12-pem": "^3.0.3",
1692 | "jws": "^4.0.0",
1693 | "mime": "^2.2.0"
1694 | },
1695 | "dependencies": {
1696 | "jwa": {
1697 | "version": "2.0.0",
1698 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
1699 | "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
1700 | "requires": {
1701 | "buffer-equal-constant-time": "1.0.1",
1702 | "ecdsa-sig-formatter": "1.0.11",
1703 | "safe-buffer": "^5.0.1"
1704 | }
1705 | },
1706 | "jws": {
1707 | "version": "4.0.0",
1708 | "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
1709 | "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
1710 | "requires": {
1711 | "jwa": "^2.0.0",
1712 | "safe-buffer": "^5.0.1"
1713 | }
1714 | }
1715 | }
1716 | },
1717 | "has-flag": {
1718 | "version": "3.0.0",
1719 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
1720 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
1721 | "dev": true
1722 | },
1723 | "hash-stream-validation": {
1724 | "version": "0.2.4",
1725 | "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz",
1726 | "integrity": "sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ=="
1727 | },
1728 | "http-errors": {
1729 | "version": "1.7.2",
1730 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
1731 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
1732 | "requires": {
1733 | "depd": "~1.1.2",
1734 | "inherits": "2.0.3",
1735 | "setprototypeof": "1.1.1",
1736 | "statuses": ">= 1.5.0 < 2",
1737 | "toidentifier": "1.0.0"
1738 | },
1739 | "dependencies": {
1740 | "inherits": {
1741 | "version": "2.0.3",
1742 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
1743 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
1744 | }
1745 | }
1746 | },
1747 | "http-parser-js": {
1748 | "version": "0.5.2",
1749 | "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.2.tgz",
1750 | "integrity": "sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ=="
1751 | },
1752 | "http-proxy-agent": {
1753 | "version": "4.0.1",
1754 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
1755 | "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
1756 | "requires": {
1757 | "@tootallnate/once": "1",
1758 | "agent-base": "6",
1759 | "debug": "4"
1760 | },
1761 | "dependencies": {
1762 | "agent-base": {
1763 | "version": "6.0.1",
1764 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz",
1765 | "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==",
1766 | "requires": {
1767 | "debug": "4"
1768 | }
1769 | },
1770 | "debug": {
1771 | "version": "4.2.0",
1772 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
1773 | "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
1774 | "requires": {
1775 | "ms": "2.1.2"
1776 | }
1777 | }
1778 | }
1779 | },
1780 | "https-proxy-agent": {
1781 | "version": "3.0.1",
1782 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz",
1783 | "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==",
1784 | "requires": {
1785 | "agent-base": "^4.3.0",
1786 | "debug": "^3.1.0"
1787 | }
1788 | },
1789 | "iconv-lite": {
1790 | "version": "0.4.24",
1791 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
1792 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
1793 | "requires": {
1794 | "safer-buffer": ">= 2.1.2 < 3"
1795 | }
1796 | },
1797 | "ignore": {
1798 | "version": "4.0.6",
1799 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
1800 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
1801 | "dev": true
1802 | },
1803 | "import-fresh": {
1804 | "version": "3.2.1",
1805 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
1806 | "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
1807 | "dev": true,
1808 | "requires": {
1809 | "parent-module": "^1.0.0",
1810 | "resolve-from": "^4.0.0"
1811 | }
1812 | },
1813 | "imurmurhash": {
1814 | "version": "0.1.4",
1815 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
1816 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
1817 | },
1818 | "inflight": {
1819 | "version": "1.0.6",
1820 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
1821 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
1822 | "requires": {
1823 | "once": "^1.3.0",
1824 | "wrappy": "1"
1825 | }
1826 | },
1827 | "inherits": {
1828 | "version": "2.0.4",
1829 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1830 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
1831 | },
1832 | "inquirer": {
1833 | "version": "6.5.2",
1834 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
1835 | "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
1836 | "dev": true,
1837 | "requires": {
1838 | "ansi-escapes": "^3.2.0",
1839 | "chalk": "^2.4.2",
1840 | "cli-cursor": "^2.1.0",
1841 | "cli-width": "^2.0.0",
1842 | "external-editor": "^3.0.3",
1843 | "figures": "^2.0.0",
1844 | "lodash": "^4.17.12",
1845 | "mute-stream": "0.0.7",
1846 | "run-async": "^2.2.0",
1847 | "rxjs": "^6.4.0",
1848 | "string-width": "^2.1.0",
1849 | "strip-ansi": "^5.1.0",
1850 | "through": "^2.3.6"
1851 | },
1852 | "dependencies": {
1853 | "ansi-regex": {
1854 | "version": "4.1.0",
1855 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
1856 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
1857 | "dev": true
1858 | },
1859 | "strip-ansi": {
1860 | "version": "5.2.0",
1861 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
1862 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
1863 | "dev": true,
1864 | "requires": {
1865 | "ansi-regex": "^4.1.0"
1866 | }
1867 | }
1868 | }
1869 | },
1870 | "ipaddr.js": {
1871 | "version": "1.9.0",
1872 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
1873 | "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
1874 | },
1875 | "is-fullwidth-code-point": {
1876 | "version": "2.0.0",
1877 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
1878 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
1879 | "dev": true
1880 | },
1881 | "is-obj": {
1882 | "version": "2.0.0",
1883 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
1884 | "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="
1885 | },
1886 | "is-promise": {
1887 | "version": "2.1.0",
1888 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
1889 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
1890 | "dev": true
1891 | },
1892 | "is-stream": {
1893 | "version": "2.0.0",
1894 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
1895 | "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw=="
1896 | },
1897 | "is-stream-ended": {
1898 | "version": "0.1.4",
1899 | "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz",
1900 | "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==",
1901 | "optional": true
1902 | },
1903 | "is-typedarray": {
1904 | "version": "1.0.0",
1905 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
1906 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
1907 | },
1908 | "isarray": {
1909 | "version": "1.0.0",
1910 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
1911 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
1912 | },
1913 | "isexe": {
1914 | "version": "2.0.0",
1915 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
1916 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
1917 | "dev": true
1918 | },
1919 | "js-tokens": {
1920 | "version": "4.0.0",
1921 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
1922 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
1923 | "dev": true
1924 | },
1925 | "js-yaml": {
1926 | "version": "3.13.1",
1927 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
1928 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
1929 | "dev": true,
1930 | "requires": {
1931 | "argparse": "^1.0.7",
1932 | "esprima": "^4.0.0"
1933 | }
1934 | },
1935 | "json-bigint": {
1936 | "version": "1.0.0",
1937 | "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
1938 | "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
1939 | "requires": {
1940 | "bignumber.js": "^9.0.0"
1941 | }
1942 | },
1943 | "json-schema-traverse": {
1944 | "version": "0.4.1",
1945 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
1946 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
1947 | "dev": true
1948 | },
1949 | "json-stable-stringify-without-jsonify": {
1950 | "version": "1.0.1",
1951 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
1952 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
1953 | "dev": true
1954 | },
1955 | "jsonwebtoken": {
1956 | "version": "8.5.1",
1957 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
1958 | "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
1959 | "requires": {
1960 | "jws": "^3.2.2",
1961 | "lodash.includes": "^4.3.0",
1962 | "lodash.isboolean": "^3.0.3",
1963 | "lodash.isinteger": "^4.0.4",
1964 | "lodash.isnumber": "^3.0.3",
1965 | "lodash.isplainobject": "^4.0.6",
1966 | "lodash.isstring": "^4.0.1",
1967 | "lodash.once": "^4.0.0",
1968 | "ms": "^2.1.1",
1969 | "semver": "^5.6.0"
1970 | },
1971 | "dependencies": {
1972 | "semver": {
1973 | "version": "5.7.1",
1974 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
1975 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
1976 | }
1977 | }
1978 | },
1979 | "jwa": {
1980 | "version": "1.4.1",
1981 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
1982 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
1983 | "requires": {
1984 | "buffer-equal-constant-time": "1.0.1",
1985 | "ecdsa-sig-formatter": "1.0.11",
1986 | "safe-buffer": "^5.0.1"
1987 | }
1988 | },
1989 | "jws": {
1990 | "version": "3.2.2",
1991 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
1992 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
1993 | "requires": {
1994 | "jwa": "^1.4.1",
1995 | "safe-buffer": "^5.0.1"
1996 | }
1997 | },
1998 | "levn": {
1999 | "version": "0.3.0",
2000 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
2001 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
2002 | "dev": true,
2003 | "requires": {
2004 | "prelude-ls": "~1.1.2",
2005 | "type-check": "~0.3.2"
2006 | }
2007 | },
2008 | "listenercount": {
2009 | "version": "1.0.1",
2010 | "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
2011 | "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc="
2012 | },
2013 | "lodash": {
2014 | "version": "4.17.21",
2015 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
2016 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
2017 | },
2018 | "lodash.camelcase": {
2019 | "version": "4.3.0",
2020 | "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
2021 | "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
2022 | "optional": true
2023 | },
2024 | "lodash.includes": {
2025 | "version": "4.3.0",
2026 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
2027 | "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
2028 | },
2029 | "lodash.isboolean": {
2030 | "version": "3.0.3",
2031 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
2032 | "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
2033 | },
2034 | "lodash.isinteger": {
2035 | "version": "4.0.4",
2036 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
2037 | "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
2038 | },
2039 | "lodash.isnumber": {
2040 | "version": "3.0.3",
2041 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
2042 | "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
2043 | },
2044 | "lodash.isplainobject": {
2045 | "version": "4.0.6",
2046 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
2047 | "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
2048 | },
2049 | "lodash.isstring": {
2050 | "version": "4.0.1",
2051 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
2052 | "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
2053 | },
2054 | "lodash.once": {
2055 | "version": "4.1.1",
2056 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
2057 | "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
2058 | },
2059 | "long": {
2060 | "version": "4.0.0",
2061 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
2062 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==",
2063 | "optional": true
2064 | },
2065 | "lru-cache": {
2066 | "version": "6.0.0",
2067 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
2068 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
2069 | "requires": {
2070 | "yallist": "^4.0.0"
2071 | }
2072 | },
2073 | "make-dir": {
2074 | "version": "3.1.0",
2075 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
2076 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
2077 | "requires": {
2078 | "semver": "^6.0.0"
2079 | }
2080 | },
2081 | "media-typer": {
2082 | "version": "0.3.0",
2083 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
2084 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
2085 | },
2086 | "merge-descriptors": {
2087 | "version": "1.0.1",
2088 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
2089 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
2090 | },
2091 | "methods": {
2092 | "version": "1.1.2",
2093 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
2094 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
2095 | },
2096 | "mime": {
2097 | "version": "2.4.4",
2098 | "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
2099 | "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
2100 | },
2101 | "mime-db": {
2102 | "version": "1.42.0",
2103 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz",
2104 | "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ=="
2105 | },
2106 | "mime-types": {
2107 | "version": "2.1.25",
2108 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz",
2109 | "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==",
2110 | "requires": {
2111 | "mime-db": "1.42.0"
2112 | }
2113 | },
2114 | "mimic-fn": {
2115 | "version": "2.1.0",
2116 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
2117 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
2118 | },
2119 | "minimatch": {
2120 | "version": "3.0.4",
2121 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
2122 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
2123 | "requires": {
2124 | "brace-expansion": "^1.1.7"
2125 | }
2126 | },
2127 | "minimist": {
2128 | "version": "1.2.5",
2129 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
2130 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
2131 | },
2132 | "mkdirp": {
2133 | "version": "0.5.5",
2134 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
2135 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
2136 | "requires": {
2137 | "minimist": "^1.2.5"
2138 | }
2139 | },
2140 | "ms": {
2141 | "version": "2.1.2",
2142 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
2143 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
2144 | },
2145 | "mute-stream": {
2146 | "version": "0.0.7",
2147 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
2148 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
2149 | "dev": true
2150 | },
2151 | "natural-compare": {
2152 | "version": "1.4.0",
2153 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
2154 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
2155 | "dev": true
2156 | },
2157 | "negotiator": {
2158 | "version": "0.6.2",
2159 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
2160 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
2161 | },
2162 | "nice-try": {
2163 | "version": "1.0.5",
2164 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
2165 | "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
2166 | "dev": true
2167 | },
2168 | "node-fetch": {
2169 | "version": "2.6.1",
2170 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
2171 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
2172 | },
2173 | "node-forge": {
2174 | "version": "0.10.0",
2175 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
2176 | "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
2177 | },
2178 | "object-assign": {
2179 | "version": "4.1.1",
2180 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
2181 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
2182 | },
2183 | "on-finished": {
2184 | "version": "2.3.0",
2185 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
2186 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
2187 | "requires": {
2188 | "ee-first": "1.1.1"
2189 | }
2190 | },
2191 | "once": {
2192 | "version": "1.4.0",
2193 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
2194 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
2195 | "requires": {
2196 | "wrappy": "1"
2197 | }
2198 | },
2199 | "onetime": {
2200 | "version": "5.1.2",
2201 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
2202 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
2203 | "requires": {
2204 | "mimic-fn": "^2.1.0"
2205 | }
2206 | },
2207 | "optionator": {
2208 | "version": "0.8.3",
2209 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
2210 | "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
2211 | "dev": true,
2212 | "requires": {
2213 | "deep-is": "~0.1.3",
2214 | "fast-levenshtein": "~2.0.6",
2215 | "levn": "~0.3.0",
2216 | "prelude-ls": "~1.1.2",
2217 | "type-check": "~0.3.2",
2218 | "word-wrap": "~1.2.3"
2219 | }
2220 | },
2221 | "os-tmpdir": {
2222 | "version": "1.0.2",
2223 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
2224 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
2225 | "dev": true
2226 | },
2227 | "p-limit": {
2228 | "version": "3.0.2",
2229 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz",
2230 | "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==",
2231 | "requires": {
2232 | "p-try": "^2.0.0"
2233 | }
2234 | },
2235 | "p-try": {
2236 | "version": "2.2.0",
2237 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
2238 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
2239 | },
2240 | "parent-module": {
2241 | "version": "1.0.1",
2242 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
2243 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
2244 | "dev": true,
2245 | "requires": {
2246 | "callsites": "^3.0.0"
2247 | }
2248 | },
2249 | "parseurl": {
2250 | "version": "1.3.3",
2251 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
2252 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
2253 | },
2254 | "path-is-absolute": {
2255 | "version": "1.0.1",
2256 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
2257 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
2258 | },
2259 | "path-is-inside": {
2260 | "version": "1.0.2",
2261 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
2262 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
2263 | "dev": true
2264 | },
2265 | "path-key": {
2266 | "version": "2.0.1",
2267 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
2268 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
2269 | "dev": true
2270 | },
2271 | "path-to-regexp": {
2272 | "version": "0.1.7",
2273 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
2274 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
2275 | },
2276 | "pend": {
2277 | "version": "1.2.0",
2278 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
2279 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
2280 | },
2281 | "prelude-ls": {
2282 | "version": "1.1.2",
2283 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
2284 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
2285 | "dev": true
2286 | },
2287 | "process-nextick-args": {
2288 | "version": "2.0.1",
2289 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
2290 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
2291 | },
2292 | "progress": {
2293 | "version": "2.0.3",
2294 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
2295 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
2296 | },
2297 | "protobufjs": {
2298 | "version": "6.10.1",
2299 | "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.10.1.tgz",
2300 | "integrity": "sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ==",
2301 | "optional": true,
2302 | "requires": {
2303 | "@protobufjs/aspromise": "^1.1.2",
2304 | "@protobufjs/base64": "^1.1.2",
2305 | "@protobufjs/codegen": "^2.0.4",
2306 | "@protobufjs/eventemitter": "^1.1.0",
2307 | "@protobufjs/fetch": "^1.1.0",
2308 | "@protobufjs/float": "^1.0.2",
2309 | "@protobufjs/inquire": "^1.1.0",
2310 | "@protobufjs/path": "^1.1.2",
2311 | "@protobufjs/pool": "^1.1.0",
2312 | "@protobufjs/utf8": "^1.1.0",
2313 | "@types/long": "^4.0.1",
2314 | "@types/node": "^13.7.0",
2315 | "long": "^4.0.0"
2316 | },
2317 | "dependencies": {
2318 | "@types/node": {
2319 | "version": "13.13.23",
2320 | "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.23.tgz",
2321 | "integrity": "sha512-L31WmMJYKb15PDqFWutn8HNwrNK6CE6bkWgSB0dO1XpNoHrszVKV1Clcnfgd6c/oG54TVF8XQEvY2gQrW8K6Mw==",
2322 | "optional": true
2323 | }
2324 | }
2325 | },
2326 | "proxy-addr": {
2327 | "version": "2.0.5",
2328 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
2329 | "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
2330 | "requires": {
2331 | "forwarded": "~0.1.2",
2332 | "ipaddr.js": "1.9.0"
2333 | }
2334 | },
2335 | "proxy-from-env": {
2336 | "version": "1.0.0",
2337 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
2338 | "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4="
2339 | },
2340 | "pump": {
2341 | "version": "3.0.0",
2342 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
2343 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
2344 | "requires": {
2345 | "end-of-stream": "^1.1.0",
2346 | "once": "^1.3.1"
2347 | }
2348 | },
2349 | "pumpify": {
2350 | "version": "2.0.1",
2351 | "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz",
2352 | "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==",
2353 | "requires": {
2354 | "duplexify": "^4.1.1",
2355 | "inherits": "^2.0.3",
2356 | "pump": "^3.0.0"
2357 | },
2358 | "dependencies": {
2359 | "duplexify": {
2360 | "version": "4.1.1",
2361 | "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.1.tgz",
2362 | "integrity": "sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==",
2363 | "requires": {
2364 | "end-of-stream": "^1.4.1",
2365 | "inherits": "^2.0.3",
2366 | "readable-stream": "^3.1.1",
2367 | "stream-shift": "^1.0.0"
2368 | }
2369 | }
2370 | }
2371 | },
2372 | "punycode": {
2373 | "version": "2.1.1",
2374 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
2375 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
2376 | "dev": true
2377 | },
2378 | "puppeteer": {
2379 | "version": "2.0.0",
2380 | "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-2.0.0.tgz",
2381 | "integrity": "sha512-t3MmTWzQxPRP71teU6l0jX47PHXlc4Z52sQv4LJQSZLq1ttkKS2yGM3gaI57uQwZkNaoGd0+HPPMELZkcyhlqA==",
2382 | "requires": {
2383 | "debug": "^4.1.0",
2384 | "extract-zip": "^1.6.6",
2385 | "https-proxy-agent": "^3.0.0",
2386 | "mime": "^2.0.3",
2387 | "progress": "^2.0.1",
2388 | "proxy-from-env": "^1.0.0",
2389 | "rimraf": "^2.6.1",
2390 | "ws": "^6.1.0"
2391 | },
2392 | "dependencies": {
2393 | "debug": {
2394 | "version": "4.1.1",
2395 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
2396 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
2397 | "requires": {
2398 | "ms": "^2.1.1"
2399 | }
2400 | }
2401 | }
2402 | },
2403 | "qs": {
2404 | "version": "6.7.0",
2405 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
2406 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
2407 | },
2408 | "range-parser": {
2409 | "version": "1.2.1",
2410 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
2411 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
2412 | },
2413 | "raw-body": {
2414 | "version": "2.4.0",
2415 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
2416 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
2417 | "requires": {
2418 | "bytes": "3.1.0",
2419 | "http-errors": "1.7.2",
2420 | "iconv-lite": "0.4.24",
2421 | "unpipe": "1.0.0"
2422 | }
2423 | },
2424 | "readable-stream": {
2425 | "version": "3.6.0",
2426 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
2427 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
2428 | "requires": {
2429 | "inherits": "^2.0.3",
2430 | "string_decoder": "^1.1.1",
2431 | "util-deprecate": "^1.0.1"
2432 | }
2433 | },
2434 | "regexpp": {
2435 | "version": "2.0.1",
2436 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
2437 | "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
2438 | "dev": true
2439 | },
2440 | "require-directory": {
2441 | "version": "2.1.1",
2442 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
2443 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
2444 | "optional": true
2445 | },
2446 | "resolve-from": {
2447 | "version": "4.0.0",
2448 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
2449 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
2450 | "dev": true
2451 | },
2452 | "restore-cursor": {
2453 | "version": "2.0.0",
2454 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
2455 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
2456 | "dev": true,
2457 | "requires": {
2458 | "onetime": "^2.0.0",
2459 | "signal-exit": "^3.0.2"
2460 | },
2461 | "dependencies": {
2462 | "mimic-fn": {
2463 | "version": "1.2.0",
2464 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
2465 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
2466 | "dev": true
2467 | },
2468 | "onetime": {
2469 | "version": "2.0.1",
2470 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
2471 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
2472 | "dev": true,
2473 | "requires": {
2474 | "mimic-fn": "^1.0.0"
2475 | }
2476 | }
2477 | }
2478 | },
2479 | "retry-request": {
2480 | "version": "4.1.3",
2481 | "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.1.3.tgz",
2482 | "integrity": "sha512-QnRZUpuPNgX0+D1xVxul6DbJ9slvo4Rm6iV/dn63e048MvGbUZiKySVt6Tenp04JqmchxjiLltGerOJys7kJYQ==",
2483 | "requires": {
2484 | "debug": "^4.1.1"
2485 | },
2486 | "dependencies": {
2487 | "debug": {
2488 | "version": "4.2.0",
2489 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
2490 | "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
2491 | "requires": {
2492 | "ms": "2.1.2"
2493 | }
2494 | }
2495 | }
2496 | },
2497 | "rimraf": {
2498 | "version": "2.7.1",
2499 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
2500 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
2501 | "requires": {
2502 | "glob": "^7.1.3"
2503 | }
2504 | },
2505 | "run-async": {
2506 | "version": "2.3.0",
2507 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
2508 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
2509 | "dev": true,
2510 | "requires": {
2511 | "is-promise": "^2.1.0"
2512 | }
2513 | },
2514 | "rxjs": {
2515 | "version": "6.5.3",
2516 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz",
2517 | "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==",
2518 | "dev": true,
2519 | "requires": {
2520 | "tslib": "^1.9.0"
2521 | }
2522 | },
2523 | "safe-buffer": {
2524 | "version": "5.1.2",
2525 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
2526 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
2527 | },
2528 | "safer-buffer": {
2529 | "version": "2.1.2",
2530 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
2531 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
2532 | },
2533 | "semver": {
2534 | "version": "6.3.0",
2535 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
2536 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
2537 | },
2538 | "send": {
2539 | "version": "0.17.1",
2540 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
2541 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
2542 | "requires": {
2543 | "debug": "2.6.9",
2544 | "depd": "~1.1.2",
2545 | "destroy": "~1.0.4",
2546 | "encodeurl": "~1.0.2",
2547 | "escape-html": "~1.0.3",
2548 | "etag": "~1.8.1",
2549 | "fresh": "0.5.2",
2550 | "http-errors": "~1.7.2",
2551 | "mime": "1.6.0",
2552 | "ms": "2.1.1",
2553 | "on-finished": "~2.3.0",
2554 | "range-parser": "~1.2.1",
2555 | "statuses": "~1.5.0"
2556 | },
2557 | "dependencies": {
2558 | "debug": {
2559 | "version": "2.6.9",
2560 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
2561 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
2562 | "requires": {
2563 | "ms": "2.0.0"
2564 | },
2565 | "dependencies": {
2566 | "ms": {
2567 | "version": "2.0.0",
2568 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
2569 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
2570 | }
2571 | }
2572 | },
2573 | "mime": {
2574 | "version": "1.6.0",
2575 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
2576 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
2577 | },
2578 | "ms": {
2579 | "version": "2.1.1",
2580 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
2581 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
2582 | }
2583 | }
2584 | },
2585 | "serve-static": {
2586 | "version": "1.14.1",
2587 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
2588 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
2589 | "requires": {
2590 | "encodeurl": "~1.0.2",
2591 | "escape-html": "~1.0.3",
2592 | "parseurl": "~1.3.3",
2593 | "send": "0.17.1"
2594 | }
2595 | },
2596 | "setimmediate": {
2597 | "version": "1.0.5",
2598 | "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
2599 | "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
2600 | },
2601 | "setprototypeof": {
2602 | "version": "1.1.1",
2603 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
2604 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
2605 | },
2606 | "shebang-command": {
2607 | "version": "1.2.0",
2608 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
2609 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
2610 | "dev": true,
2611 | "requires": {
2612 | "shebang-regex": "^1.0.0"
2613 | }
2614 | },
2615 | "shebang-regex": {
2616 | "version": "1.0.0",
2617 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
2618 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
2619 | "dev": true
2620 | },
2621 | "signal-exit": {
2622 | "version": "3.0.2",
2623 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
2624 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
2625 | },
2626 | "slice-ansi": {
2627 | "version": "2.1.0",
2628 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
2629 | "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
2630 | "dev": true,
2631 | "requires": {
2632 | "ansi-styles": "^3.2.0",
2633 | "astral-regex": "^1.0.0",
2634 | "is-fullwidth-code-point": "^2.0.0"
2635 | }
2636 | },
2637 | "snakeize": {
2638 | "version": "0.1.0",
2639 | "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz",
2640 | "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0="
2641 | },
2642 | "sprintf-js": {
2643 | "version": "1.0.3",
2644 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
2645 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
2646 | "dev": true
2647 | },
2648 | "statuses": {
2649 | "version": "1.5.0",
2650 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
2651 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
2652 | },
2653 | "stream-events": {
2654 | "version": "1.0.5",
2655 | "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz",
2656 | "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==",
2657 | "requires": {
2658 | "stubs": "^3.0.0"
2659 | }
2660 | },
2661 | "stream-shift": {
2662 | "version": "1.0.1",
2663 | "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
2664 | "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
2665 | },
2666 | "streamsearch": {
2667 | "version": "0.1.2",
2668 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
2669 | "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
2670 | },
2671 | "string-width": {
2672 | "version": "2.1.1",
2673 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
2674 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
2675 | "dev": true,
2676 | "requires": {
2677 | "is-fullwidth-code-point": "^2.0.0",
2678 | "strip-ansi": "^4.0.0"
2679 | }
2680 | },
2681 | "string_decoder": {
2682 | "version": "1.1.1",
2683 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
2684 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
2685 | "requires": {
2686 | "safe-buffer": "~5.1.0"
2687 | }
2688 | },
2689 | "strip-ansi": {
2690 | "version": "4.0.0",
2691 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
2692 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
2693 | "dev": true,
2694 | "requires": {
2695 | "ansi-regex": "^3.0.0"
2696 | }
2697 | },
2698 | "strip-json-comments": {
2699 | "version": "2.0.1",
2700 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
2701 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
2702 | "dev": true
2703 | },
2704 | "stubs": {
2705 | "version": "3.0.0",
2706 | "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz",
2707 | "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls="
2708 | },
2709 | "supports-color": {
2710 | "version": "5.5.0",
2711 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
2712 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
2713 | "dev": true,
2714 | "requires": {
2715 | "has-flag": "^3.0.0"
2716 | }
2717 | },
2718 | "table": {
2719 | "version": "5.4.6",
2720 | "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
2721 | "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
2722 | "dev": true,
2723 | "requires": {
2724 | "ajv": "^6.10.2",
2725 | "lodash": "^4.17.14",
2726 | "slice-ansi": "^2.1.0",
2727 | "string-width": "^3.0.0"
2728 | },
2729 | "dependencies": {
2730 | "ansi-regex": {
2731 | "version": "4.1.0",
2732 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
2733 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
2734 | "dev": true
2735 | },
2736 | "string-width": {
2737 | "version": "3.1.0",
2738 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
2739 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
2740 | "dev": true,
2741 | "requires": {
2742 | "emoji-regex": "^7.0.1",
2743 | "is-fullwidth-code-point": "^2.0.0",
2744 | "strip-ansi": "^5.1.0"
2745 | }
2746 | },
2747 | "strip-ansi": {
2748 | "version": "5.2.0",
2749 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
2750 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
2751 | "dev": true,
2752 | "requires": {
2753 | "ansi-regex": "^4.1.0"
2754 | }
2755 | }
2756 | }
2757 | },
2758 | "teeny-request": {
2759 | "version": "7.0.1",
2760 | "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.0.1.tgz",
2761 | "integrity": "sha512-sasJmQ37klOlplL4Ia/786M5YlOcoLGQyq2TE4WHSRupbAuDaQW0PfVxV4MtdBtRJ4ngzS+1qim8zP6Zp35qCw==",
2762 | "requires": {
2763 | "http-proxy-agent": "^4.0.0",
2764 | "https-proxy-agent": "^5.0.0",
2765 | "node-fetch": "^2.6.1",
2766 | "stream-events": "^1.0.5",
2767 | "uuid": "^8.0.0"
2768 | },
2769 | "dependencies": {
2770 | "agent-base": {
2771 | "version": "6.0.1",
2772 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz",
2773 | "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==",
2774 | "requires": {
2775 | "debug": "4"
2776 | }
2777 | },
2778 | "debug": {
2779 | "version": "4.2.0",
2780 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
2781 | "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
2782 | "requires": {
2783 | "ms": "2.1.2"
2784 | }
2785 | },
2786 | "https-proxy-agent": {
2787 | "version": "5.0.0",
2788 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
2789 | "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
2790 | "requires": {
2791 | "agent-base": "6",
2792 | "debug": "4"
2793 | }
2794 | }
2795 | }
2796 | },
2797 | "text-table": {
2798 | "version": "0.2.0",
2799 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
2800 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
2801 | "dev": true
2802 | },
2803 | "through": {
2804 | "version": "2.3.8",
2805 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
2806 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
2807 | "dev": true
2808 | },
2809 | "tmp": {
2810 | "version": "0.0.33",
2811 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
2812 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
2813 | "dev": true,
2814 | "requires": {
2815 | "os-tmpdir": "~1.0.2"
2816 | }
2817 | },
2818 | "toidentifier": {
2819 | "version": "1.0.0",
2820 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
2821 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
2822 | },
2823 | "traverse": {
2824 | "version": "0.3.9",
2825 | "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz",
2826 | "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk="
2827 | },
2828 | "tslib": {
2829 | "version": "1.10.0",
2830 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
2831 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
2832 | "dev": true
2833 | },
2834 | "type-check": {
2835 | "version": "0.3.2",
2836 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
2837 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
2838 | "dev": true,
2839 | "requires": {
2840 | "prelude-ls": "~1.1.2"
2841 | }
2842 | },
2843 | "type-is": {
2844 | "version": "1.6.18",
2845 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
2846 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
2847 | "requires": {
2848 | "media-typer": "0.3.0",
2849 | "mime-types": "~2.1.24"
2850 | }
2851 | },
2852 | "typedarray": {
2853 | "version": "0.0.6",
2854 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
2855 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
2856 | },
2857 | "typedarray-to-buffer": {
2858 | "version": "3.1.5",
2859 | "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
2860 | "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
2861 | "requires": {
2862 | "is-typedarray": "^1.0.0"
2863 | }
2864 | },
2865 | "unique-string": {
2866 | "version": "2.0.0",
2867 | "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
2868 | "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
2869 | "requires": {
2870 | "crypto-random-string": "^2.0.0"
2871 | }
2872 | },
2873 | "unpipe": {
2874 | "version": "1.0.0",
2875 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
2876 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
2877 | },
2878 | "unzipper": {
2879 | "version": "0.10.10",
2880 | "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.10.tgz",
2881 | "integrity": "sha512-wEgtqtrnJ/9zIBsQb8UIxOhAH1eTHfi7D/xvmrUoMEePeI6u24nq1wigazbIFtHt6ANYXdEVTvc8XYNlTurs7A==",
2882 | "requires": {
2883 | "big-integer": "^1.6.17",
2884 | "binary": "~0.3.0",
2885 | "bluebird": "~3.4.1",
2886 | "buffer-indexof-polyfill": "~1.0.0",
2887 | "duplexer2": "~0.1.4",
2888 | "fstream": "^1.0.12",
2889 | "graceful-fs": "^4.2.2",
2890 | "listenercount": "~1.0.1",
2891 | "readable-stream": "~2.3.6",
2892 | "setimmediate": "~1.0.4"
2893 | },
2894 | "dependencies": {
2895 | "readable-stream": {
2896 | "version": "2.3.7",
2897 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
2898 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
2899 | "requires": {
2900 | "core-util-is": "~1.0.0",
2901 | "inherits": "~2.0.3",
2902 | "isarray": "~1.0.0",
2903 | "process-nextick-args": "~2.0.0",
2904 | "safe-buffer": "~5.1.1",
2905 | "string_decoder": "~1.1.1",
2906 | "util-deprecate": "~1.0.1"
2907 | }
2908 | }
2909 | }
2910 | },
2911 | "uri-js": {
2912 | "version": "4.2.2",
2913 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
2914 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
2915 | "dev": true,
2916 | "requires": {
2917 | "punycode": "^2.1.0"
2918 | }
2919 | },
2920 | "util-deprecate": {
2921 | "version": "1.0.2",
2922 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
2923 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
2924 | },
2925 | "utils-merge": {
2926 | "version": "1.0.1",
2927 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
2928 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
2929 | },
2930 | "uuid": {
2931 | "version": "8.3.1",
2932 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz",
2933 | "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg=="
2934 | },
2935 | "vary": {
2936 | "version": "1.1.2",
2937 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
2938 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
2939 | },
2940 | "websocket-driver": {
2941 | "version": "0.7.4",
2942 | "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
2943 | "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
2944 | "requires": {
2945 | "http-parser-js": ">=0.5.1",
2946 | "safe-buffer": ">=5.1.0",
2947 | "websocket-extensions": ">=0.1.1"
2948 | }
2949 | },
2950 | "websocket-extensions": {
2951 | "version": "0.1.4",
2952 | "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
2953 | "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg=="
2954 | },
2955 | "which": {
2956 | "version": "1.3.1",
2957 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
2958 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
2959 | "dev": true,
2960 | "requires": {
2961 | "isexe": "^2.0.0"
2962 | }
2963 | },
2964 | "word-wrap": {
2965 | "version": "1.2.3",
2966 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
2967 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
2968 | "dev": true
2969 | },
2970 | "wrappy": {
2971 | "version": "1.0.2",
2972 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
2973 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
2974 | },
2975 | "write": {
2976 | "version": "1.0.3",
2977 | "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
2978 | "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
2979 | "dev": true,
2980 | "requires": {
2981 | "mkdirp": "^0.5.1"
2982 | }
2983 | },
2984 | "write-file-atomic": {
2985 | "version": "3.0.3",
2986 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
2987 | "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
2988 | "requires": {
2989 | "imurmurhash": "^0.1.4",
2990 | "is-typedarray": "^1.0.0",
2991 | "signal-exit": "^3.0.2",
2992 | "typedarray-to-buffer": "^3.1.5"
2993 | }
2994 | },
2995 | "ws": {
2996 | "version": "6.2.1",
2997 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
2998 | "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
2999 | "requires": {
3000 | "async-limiter": "~1.0.0"
3001 | }
3002 | },
3003 | "xdg-basedir": {
3004 | "version": "4.0.0",
3005 | "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz",
3006 | "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q=="
3007 | },
3008 | "yallist": {
3009 | "version": "4.0.0",
3010 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
3011 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
3012 | },
3013 | "yauzl": {
3014 | "version": "2.10.0",
3015 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
3016 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
3017 | "requires": {
3018 | "buffer-crc32": "~0.2.3",
3019 | "fd-slicer": "~1.1.0"
3020 | }
3021 | }
3022 | }
3023 | }
3024 |
--------------------------------------------------------------------------------
/whatsapp/functions/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "whatsapp-morning-hail",
3 | "description": "Firebase/Google Cloud function to hail parents on WhatsApp automatically in the morning that is executed daily via scheduler! It keeps your WhatsApp session in Cloud Storage over Chrome's user data directory and sends a message to a WhatsApp group every morning with headless chrome instance using Puppeteer on a cloud function.",
4 | "scripts": {
5 | "lint": "eslint .",
6 | "serve": "firebase serve --only functions",
7 | "shell": "firebase functions:shell",
8 | "preemulate": "export GOOGLE_APPLICATION_CREDENTIALS=./secret/morning-hail-56d9123ccf2d.json",
9 | "emulate": "firebase emulators:start --only functions",
10 | "start": "npm run shell",
11 | "deploy": "firebase deploy --only functions",
12 | "logs": "firebase functions:log"
13 | },
14 | "engines": {
15 | "node": "8"
16 | },
17 | "dependencies": {
18 | "@google-cloud/storage": "^5.3.0",
19 | "firebase-admin": "^9.2.0",
20 | "firebase-functions": "^3.3.0",
21 | "puppeteer": "^2.0.0",
22 | "unzipper": "^0.10.10"
23 | },
24 | "devDependencies": {
25 | "eslint": "5.16.0",
26 | "eslint-plugin-promise": "^4.0.1",
27 | "firebase-functions-test": "^0.1.6"
28 | },
29 | "private": true
30 | }
31 |
--------------------------------------------------------------------------------
/whatsapp/storage.rules:
--------------------------------------------------------------------------------
1 | service firebase.storage {
2 | match /b/{bucket}/o {
3 | match /{allPaths=**} {
4 | allow read, write: if false;
5 | }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/whatsapp/whatsapp-demo.js:
--------------------------------------------------------------------------------
1 | const puppeteer = require('puppeteer');
2 | const { getTodaysMessage, sendMessageToGroup } = require('./functions/helpers');
3 |
4 | (async () => {
5 |
6 | try {
7 | const path = require('path');
8 | const browser = await puppeteer.launch({ headless: false, args: [`--user-data-dir=${path.resolve(__dirname, '.tmp')}`] });
9 | const page = await browser.newPage();
10 |
11 | try {
12 | await sendMessageToGroup(page, getTodaysMessage(), 'Bizimkiler', true);
13 | } finally {
14 | await page.close();
15 | await browser.close();
16 | }
17 | } catch(e) {
18 | console.error(e);
19 | process.exit(1);
20 | }
21 | })();
22 |
--------------------------------------------------------------------------------