├── .gitignore
├── LICENSE
├── README.md
├── assets
├── bigquery.png
├── cover.svg
└── page_example.png
├── package.json
├── packages
├── client
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ └── util.ts
│ ├── tsconfig.json
│ └── yarn.lock
└── server
│ ├── README.md
│ ├── package.json
│ ├── src
│ ├── index.ts
│ └── schemas.ts
│ ├── tsconfig.json
│ └── yarn.lock
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # Snowpack dependency directory (https://snowpack.dev/)
45 | web_modules/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 | .parcel-cache
78 |
79 | # Next.js build output
80 | .next
81 | out
82 |
83 | # Nuxt.js build / generate output
84 | .nuxt
85 | dist
86 |
87 | # Gatsby files
88 | .cache/
89 | # Comment in the public line in if your project uses Gatsby and not Next.js
90 | # https://nextjs.org/blog/next-9-1#public-directory-support
91 | # public
92 |
93 | # vuepress build output
94 | .vuepress/dist
95 |
96 | # Serverless directories
97 | .serverless/
98 |
99 | # FuseBox cache
100 | .fusebox/
101 |
102 | # DynamoDB Local files
103 | .dynamodb/
104 |
105 | # TernJS port file
106 | .tern-port
107 |
108 | # Stores VSCode versions used for testing VSCode extensions
109 | .vscode-test
110 |
111 | # yarn v2
112 | .yarn/cache
113 | .yarn/unplugged
114 | .yarn/build-state.yml
115 | .yarn/install-state.gz
116 | .pnp.*
117 |
118 |
119 |
120 |
121 | .DS_Store
122 | .env
123 | .eslintcache
124 | .stylelintcache
125 | .tsbuildinfo
126 |
127 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Instant Domain Search, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://vitals.dev)
2 |
3 | # [Instant Vitals](https://vitals.dev): Simple tools to track and improve your Web Vitals scores
4 |
5 | [](https://www.npmjs.com/package/@instantdomain/vitals-client)
6 | [](https://www.npmjs.com/package/@instantdomain/vitals-server)
7 | [](https://github.com/InstantDomainSearch/instant-vitals/blob/main/LICENSE)
8 |
9 | Instant Vitals is a tool for collecting Web Vitals metrics and storing them in [Google BigQuery](https://cloud.google.com/bigquery). The library has both a client and a server component. The client is responsible for collecting the metrics using [web-vitals](https://github.com/GoogleChrome/web-vitals), which is maintained by the Google Chrome team, and sending the metrics to the endpoint of your choice. In addition to this, the client converts HTML elements into XPath query strings so that you can easily track down where your problems are later.
10 |
11 | The server component is then used to take these metrics and send them to BigQuery. Once the metrics are in BigQuery, you can more easily query for the information you need to improve your Web Vitals scores.
12 |
13 | For now we'll assume you're using `npm` and that you have some sort of build system in place for the client. While the server component is only available for NodeJS at the moment, this library is more of a pattern than a prescription so it shouldn't be too hard to implement this yourself in your language of choice.
14 |
15 | ## Prerequisites
16 |
17 | Instant Vitals relies on Google BigQuery to store and process data. You should create an account before getting started. Be aware that the paid tier is required to use this library; however, even with a large number of users, the cost should still be very low.
18 |
19 | Once you have created an account, you will need to create a service account. The service account will need permission to create datasets and tables as well as insert records into the database. Create a key for this service account and keep it handy.
20 |
21 | ## Client Installation
22 |
23 | To get started, install the client library in your project:
24 |
25 | ```sh
26 | npm i @instantdomain/vitals-client
27 | ```
28 |
29 | Then, you can initialize the library in your browser code like so:
30 |
31 | ```typescript
32 | import { init } from "@instantdomain/vitals-client";
33 |
34 | init({ endpoint: "/api/web-vitals" });
35 | ```
36 |
37 | Here I'm using `"/api/web-vitals"` as the endpoint. You'll want to change this to an endpoint of your choice on a server that you control.
38 |
39 | ## Server Installation
40 |
41 | First, install the server library in your NodeJS project:
42 |
43 | ```sh
44 | npm i @instantdomain/vitals-server
45 | ```
46 |
47 | Then, you can initialize the server component. Here is an example request handler for the endpoint `/api/web-vitals`
48 |
49 | ```typescript
50 | import fs from "fs";
51 |
52 | import { init, streamVitals } from "@instantdomain/vitals-server";
53 |
54 | // Google libraries require service key as path to file
55 | const GOOGLE_SERVICE_KEY = process.env.GOOGLE_SERVICE_KEY;
56 | process.env.GOOGLE_APPLICATION_CREDENTIALS = "/tmp/goog_creds";
57 | fs.writeFileSync(
58 | process.env.GOOGLE_APPLICATION_CREDENTIALS,
59 | GOOGLE_SERVICE_KEY
60 | );
61 |
62 | const DATASET_ID = "web_vitals";
63 | init({ datasetId: DATASET_ID }).then().catch(console.error);
64 |
65 | // Request handler
66 | export default async (req, res) => {
67 | const body = JSON.parse(req.body);
68 | await streamVitals(body, body.name);
69 | res.status(200).end();
70 | };
71 | ```
72 |
73 | Note that here we are storing our Google Cloud service key as a string in `GOOGLE_SERVICE_KEY`. We then need to write the key to a temporary file before instructing the BigQuery library to read from that file.
74 |
75 | ## Running
76 |
77 | Once you start your server, you should see the requisite dataset and tables created in BigQuery. Once you have some visitors on your site, you should start seeing your Web Vitals metrics data in these tables:
78 |
79 | 
80 |
81 | ## Identifying opportunities for improvement
82 |
83 | Now you're ready to identify some elements on your page that are causing issues. For example, you can query for CLS violations like so:
84 |
85 | ```sql
86 | SELECT
87 | `vitalsdev.web_vitals.CLS`.Value,
88 | Node
89 | FROM
90 | `vitalsdev.web_vitals.CLS`
91 | JOIN
92 | UNNEST(Entries) AS Entry
93 | JOIN
94 | UNNEST(Entry.Sources)
95 | WHERE
96 | Node != ""
97 | ORDER BY
98 | value
99 | LIMIT
100 | 10
101 | ```
102 |
103 | This gives us the following result:
104 |
105 | | Value | Node |
106 | | --------------------- | -------------------------------------------------------- |
107 | | 4.6045324800736724E-4 | /html/body/div[1]/main/div/div/div[2]/div/div/blockquote |
108 | | 7.183070668914928E-4 | /html/body/div[1]/header/div/div/header/div |
109 | | 0.031002668277977697 | /html/body/div[1]/footer |
110 | | 0.035830703317463526 | /html/body/div[1]/main/div/div/div[2] |
111 | | 0.035830703317463526 | /html/body/div[1]/footer |
112 | | 0.035830703317463526 | /html/body/div[1]/main/div/div/div[2] |
113 | | 0.035830703317463526 | /html/body/div[1]/main/div/div/div[2] |
114 | | 0.035830703317463526 | /html/body/div[1]/footer |
115 | | 0.035830703317463526 | /html/body/div[1]/footer |
116 | | 0.03988482067913317 | /html/body/div[1]/footer |
117 |
118 | Now, you can browse to your website in Google Chrome and find the offending elements using the following code:
119 |
120 | ```javascript
121 | $x("/html/body/div[1]/main/div/div/div[2]/div/div/blockquote");
122 | ```
123 |
124 | 
125 |
126 | As you can see, you can identify which elements on the page are degrading your CLS scores. Now you can use this information to improve your users' experiences and your Web Vitals scores!
127 |
--------------------------------------------------------------------------------
/assets/bigquery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/instant-labs/instant-vitals/60e5b57e39bfeb658711bb121f668b853bb5bb7d/assets/bigquery.png
--------------------------------------------------------------------------------
/assets/cover.svg:
--------------------------------------------------------------------------------
1 |
517 |
--------------------------------------------------------------------------------
/assets/page_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/instant-labs/instant-vitals/60e5b57e39bfeb658711bb121f668b853bb5bb7d/assets/page_example.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "instant-vitals",
3 | "version": "1.0.0",
4 | "description": "Simple tools to track and improve your Web Vitals scores",
5 | "main": "index.js",
6 | "repository": "https://github.com/InstantDomainSearch/instant-vitals",
7 | "homepage": "https://vitals.dev",
8 | "license": "MIT",
9 | "private": false,
10 | "keywords": [
11 | "web vitals",
12 | "LCP",
13 | "FID",
14 | "CLS",
15 | "Largest Contentful Paint",
16 | "First Input Delay",
17 | "Cumulative Layout Shift"
18 | ],
19 | "files": [
20 | "README.md"
21 | ],
22 | "devDependencies": {
23 | "tslib": "^2.3.1"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/client/README.md:
--------------------------------------------------------------------------------
1 | # Instant Vitals Client
2 |
--------------------------------------------------------------------------------
/packages/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@instantdomain/vitals-client",
3 | "version": "0.1.4",
4 | "types": "dist/index.d.ts",
5 | "main": "dist/index.js",
6 | "license": "MIT",
7 | "files": [
8 | "/dist"
9 | ],
10 | "dependencies": {
11 | "web-vitals": "^2.1.2"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/client/src/index.ts:
--------------------------------------------------------------------------------
1 | import { getCLS, getFID, getLCP, Metric } from "web-vitals";
2 | import { getXPath, isElement, isNode } from "./util";
3 |
4 | type options = {
5 | endpoint: string;
6 | };
7 |
8 | const report = async (metric: Metric, options: options) => {
9 | const cleanedMetric = convertNodesToXPath(
10 | (metric as unknown) as Record
11 | );
12 | await fetch(options.endpoint, {
13 | body: JSON.stringify(cleanedMetric),
14 | method: "POST",
15 | });
16 | };
17 |
18 | function convertNodesToXPath(obj: Record): string {
19 | const getOmittedReplacer = () => {
20 | return (_: string, value: unknown) => {
21 | if (isElement(value) || isNode(value)) {
22 | return getXPath(value as Element);
23 | }
24 | return value;
25 | };
26 | };
27 |
28 | return JSON.parse(JSON.stringify(obj, getOmittedReplacer()));
29 | }
30 |
31 | export const init = ({ endpoint }: options) => {
32 | const start = (metric: Metric) => {
33 | report(metric, { endpoint });
34 | };
35 |
36 | getCLS(start);
37 | getFID(start);
38 | getLCP(start);
39 | };
40 |
--------------------------------------------------------------------------------
/packages/client/src/util.ts:
--------------------------------------------------------------------------------
1 | export const isBrowser = typeof window !== "undefined";
2 | export const isElement = (value: unknown): boolean => value instanceof Element;
3 | export const isNode = (value: unknown): boolean => value instanceof Node;
4 |
5 | export const getXPath = (el: Element): string => {
6 | let nodeElem = el;
7 | if (nodeElem && nodeElem.id) {
8 | return '//*[@id="' + nodeElem.id + '"]';
9 | }
10 | const parts: string[] = [];
11 | while (nodeElem && Node.ELEMENT_NODE === nodeElem.nodeType) {
12 | let nbOfPreviousSiblings = 0;
13 | let hasNextSiblings = false;
14 | let sibling = nodeElem.previousSibling;
15 | while (sibling) {
16 | if (
17 | sibling.nodeType !== Node.DOCUMENT_TYPE_NODE &&
18 | sibling.nodeName === nodeElem.nodeName
19 | ) {
20 | nbOfPreviousSiblings++;
21 | }
22 | sibling = sibling.previousSibling;
23 | }
24 | sibling = nodeElem.nextSibling;
25 | while (sibling) {
26 | if (sibling.nodeName === nodeElem.nodeName) {
27 | hasNextSiblings = true;
28 | break;
29 | }
30 | sibling = sibling.nextSibling;
31 | }
32 | const prefix = nodeElem.prefix ? nodeElem.prefix + ":" : "";
33 | const nth =
34 | nbOfPreviousSiblings || hasNextSiblings
35 | ? "[" + (nbOfPreviousSiblings + 1) + "]"
36 | : "";
37 | parts.push(prefix + nodeElem.localName + nth);
38 | nodeElem = nodeElem.parentNode as Element;
39 | }
40 | return parts.length ? "/" + parts.reverse().join("/") : "";
41 | };
42 |
--------------------------------------------------------------------------------
/packages/client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es2015",
5 | "declaration": true,
6 | "outDir": "./dist",
7 | "sourceMap": true,
8 | "strict": true,
9 | "noUnusedLocals": true,
10 | "noUnusedParameters": true,
11 | "noImplicitReturns": true,
12 | "noFallthroughCasesInSwitch": true,
13 | "downlevelIteration": true,
14 | "moduleResolution": "node",
15 | "jsx": "preserve",
16 | "esModuleInterop": true,
17 | "skipLibCheck": true,
18 | "forceConsistentCasingInFileNames": true,
19 | "isolatedModules": true,
20 | },
21 | "include": ["src", "types"],
22 | "exclude": ["node_modules"]
23 | }
--------------------------------------------------------------------------------
/packages/client/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | web-vitals@^2.1.2:
6 | version "2.1.2"
7 | resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-2.1.2.tgz#3a6c8faebf9097a6ccd17f5f45c9485d8d62dab1"
8 | integrity sha512-nZnEH8dj+vJFqCRYdvYv0a59iLXsb8jJkt+xvXfwgnkyPdsSLtKNlYmtTDiHmTNGXeSXtpjTTUcNvFtrAk6VMQ==
9 |
--------------------------------------------------------------------------------
/packages/server/README.md:
--------------------------------------------------------------------------------
1 | # instant-vitals
2 |
--------------------------------------------------------------------------------
/packages/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@instantdomain/vitals-server",
3 | "version": "0.1.3",
4 | "types": "dist/index.d.ts",
5 | "main": "dist/index.js",
6 | "license": "MIT",
7 | "files": [
8 | "/dist"
9 | ],
10 | "dependencies": {
11 | "@google-cloud/bigquery": "^5.5.0",
12 | "@types/node": "^16.11.6"
13 | },
14 | "devDependencies": {
15 | "@types/node": "^14.14.41"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/server/src/index.ts:
--------------------------------------------------------------------------------
1 | import { schemas } from "./schemas";
2 | import { BigQuery } from "@google-cloud/bigquery";
3 |
4 | interface Options {
5 | datasetId: string;
6 | }
7 |
8 | const options: Options = {
9 | datasetId: "",
10 | };
11 |
12 | export const streamVitals = async (metric: unknown, table: string) => {
13 | const bigquery = new BigQuery();
14 | try {
15 | await bigquery.dataset(options.datasetId).table(table).insert([metric]);
16 | } catch (e) {
17 | console.error(e);
18 | }
19 | };
20 |
21 | export const init = async ({ datasetId }: Options) => {
22 | options.datasetId = datasetId;
23 |
24 | const bigquery = new BigQuery();
25 |
26 | const [datasets] = await bigquery.getDatasets();
27 | if (!datasets.map((set) => set.id).includes(datasetId)) {
28 | await bigquery.createDataset(datasetId);
29 | }
30 |
31 | for (const [metricName, schema] of Object.entries(schemas)) {
32 | try {
33 | await bigquery
34 | .dataset(options.datasetId)
35 | .createTable(metricName, { schema: schema });
36 | } catch (e) {}
37 | }
38 | };
39 |
--------------------------------------------------------------------------------
/packages/server/src/schemas.ts:
--------------------------------------------------------------------------------
1 | export const schemas = {
2 | CLS: {
3 | fields: [
4 | {
5 | mode: "REQUIRED",
6 | name: "Name",
7 | type: "STRING",
8 | },
9 | {
10 | mode: "REQUIRED",
11 | name: "Value",
12 | type: "FLOAT",
13 | },
14 | {
15 | mode: "REQUIRED",
16 | name: "Delta",
17 | type: "FLOAT",
18 | },
19 | {
20 | fields: [
21 | {
22 | mode: "REQUIRED",
23 | name: "Name",
24 | type: "STRING",
25 | },
26 | {
27 | mode: "REQUIRED",
28 | name: "EntryType",
29 | type: "STRING",
30 | },
31 | {
32 | mode: "REQUIRED",
33 | name: "StartTime",
34 | type: "FLOAT",
35 | },
36 | {
37 | mode: "REQUIRED",
38 | name: "Duration",
39 | type: "INTEGER",
40 | },
41 | {
42 | mode: "REQUIRED",
43 | name: "Value",
44 | type: "FLOAT",
45 | },
46 | {
47 | mode: "REQUIRED",
48 | name: "HadRecentInput",
49 | type: "BOOLEAN",
50 | },
51 | {
52 | mode: "REQUIRED",
53 | name: "LastInputTime",
54 | type: "FLOAT",
55 | },
56 | {
57 | fields: [
58 | {
59 | mode: "REQUIRED",
60 | name: "Node",
61 | type: "STRING",
62 | },
63 | {
64 | fields: [
65 | {
66 | mode: "REQUIRED",
67 | name: "X",
68 | type: "INTEGER",
69 | },
70 | {
71 | mode: "REQUIRED",
72 | name: "Y",
73 | type: "INTEGER",
74 | },
75 | {
76 | mode: "REQUIRED",
77 | name: "Width",
78 | type: "INTEGER",
79 | },
80 | {
81 | mode: "REQUIRED",
82 | name: "Height",
83 | type: "INTEGER",
84 | },
85 | {
86 | mode: "REQUIRED",
87 | name: "Top",
88 | type: "INTEGER",
89 | },
90 | {
91 | mode: "REQUIRED",
92 | name: "Right",
93 | type: "INTEGER",
94 | },
95 | {
96 | mode: "REQUIRED",
97 | name: "Bottom",
98 | type: "INTEGER",
99 | },
100 | {
101 | mode: "REQUIRED",
102 | name: "Left",
103 | type: "INTEGER",
104 | },
105 | ],
106 | mode: "REQUIRED",
107 | name: "PreviousRect",
108 | type: "RECORD",
109 | },
110 | {
111 | fields: [
112 | {
113 | mode: "REQUIRED",
114 | name: "X",
115 | type: "INTEGER",
116 | },
117 | {
118 | mode: "REQUIRED",
119 | name: "Y",
120 | type: "INTEGER",
121 | },
122 | {
123 | mode: "REQUIRED",
124 | name: "Width",
125 | type: "INTEGER",
126 | },
127 | {
128 | mode: "REQUIRED",
129 | name: "Height",
130 | type: "INTEGER",
131 | },
132 | {
133 | mode: "REQUIRED",
134 | name: "Top",
135 | type: "INTEGER",
136 | },
137 | {
138 | mode: "REQUIRED",
139 | name: "Right",
140 | type: "INTEGER",
141 | },
142 | {
143 | mode: "REQUIRED",
144 | name: "Bottom",
145 | type: "INTEGER",
146 | },
147 | {
148 | mode: "REQUIRED",
149 | name: "Left",
150 | type: "INTEGER",
151 | },
152 | ],
153 | mode: "REQUIRED",
154 | name: "CurrentRect",
155 | type: "RECORD",
156 | },
157 | ],
158 | mode: "REPEATED",
159 | name: "Sources",
160 | type: "RECORD",
161 | },
162 | ],
163 | mode: "REPEATED",
164 | name: "Entries",
165 | type: "RECORD",
166 | },
167 | {
168 | mode: "REQUIRED",
169 | name: "ID",
170 | type: "STRING",
171 | },
172 | ],
173 | },
174 | FID: {
175 | fields: [
176 | {
177 | mode: "REQUIRED",
178 | name: "Name",
179 | type: "STRING",
180 | },
181 | {
182 | mode: "REQUIRED",
183 | name: "Value",
184 | type: "FLOAT",
185 | },
186 | {
187 | mode: "REQUIRED",
188 | name: "Delta",
189 | type: "FLOAT",
190 | },
191 | {
192 | fields: [
193 | {
194 | mode: "REQUIRED",
195 | name: "Name",
196 | type: "STRING",
197 | },
198 | {
199 | mode: "REQUIRED",
200 | name: "EntryType",
201 | type: "STRING",
202 | },
203 | {
204 | mode: "REQUIRED",
205 | name: "StartTime",
206 | type: "FLOAT",
207 | },
208 | {
209 | mode: "REQUIRED",
210 | name: "Duration",
211 | type: "INTEGER",
212 | },
213 | {
214 | mode: "REQUIRED",
215 | name: "ProcessingStart",
216 | type: "FLOAT",
217 | },
218 | {
219 | mode: "REQUIRED",
220 | name: "ProcessingEnd",
221 | type: "FLOAT",
222 | },
223 | {
224 | mode: "REQUIRED",
225 | name: "Cancelable",
226 | type: "BOOLEAN",
227 | },
228 | ],
229 | mode: "REPEATED",
230 | name: "Entries",
231 | type: "RECORD",
232 | },
233 | {
234 | mode: "REQUIRED",
235 | name: "ID",
236 | type: "STRING",
237 | },
238 | ],
239 | },
240 | FCP: {
241 | fields: [
242 | {
243 | mode: "REQUIRED",
244 | name: "Name",
245 | type: "STRING",
246 | },
247 | {
248 | mode: "REQUIRED",
249 | name: "Value",
250 | type: "FLOAT",
251 | },
252 | {
253 | mode: "REQUIRED",
254 | name: "Delta",
255 | type: "FLOAT",
256 | },
257 | {
258 | fields: [
259 | {
260 | mode: "REQUIRED",
261 | name: "Name",
262 | type: "STRING",
263 | },
264 | {
265 | mode: "REQUIRED",
266 | name: "EntryType",
267 | type: "STRING",
268 | },
269 | {
270 | mode: "REQUIRED",
271 | name: "StartTime",
272 | type: "FLOAT",
273 | },
274 | {
275 | mode: "REQUIRED",
276 | name: "Duration",
277 | type: "INTEGER",
278 | },
279 | ],
280 | mode: "REPEATED",
281 | name: "Entries",
282 | type: "RECORD",
283 | },
284 | {
285 | mode: "REQUIRED",
286 | name: "ID",
287 | type: "STRING",
288 | },
289 | ],
290 | },
291 | LCP: {
292 | fields: [
293 | {
294 | mode: "REQUIRED",
295 | name: "Name",
296 | type: "STRING",
297 | },
298 | {
299 | mode: "REQUIRED",
300 | name: "Value",
301 | type: "FLOAT",
302 | },
303 | {
304 | mode: "REQUIRED",
305 | name: "Delta",
306 | type: "FLOAT",
307 | },
308 | {
309 | fields: [
310 | {
311 | mode: "REQUIRED",
312 | name: "Name",
313 | type: "STRING",
314 | },
315 | {
316 | mode: "REQUIRED",
317 | name: "EntryType",
318 | type: "STRING",
319 | },
320 | {
321 | mode: "REQUIRED",
322 | name: "StartTime",
323 | type: "FLOAT",
324 | },
325 | {
326 | mode: "REQUIRED",
327 | name: "Duration",
328 | type: "INTEGER",
329 | },
330 | {
331 | mode: "REQUIRED",
332 | name: "Size",
333 | type: "INTEGER",
334 | },
335 | {
336 | mode: "REQUIRED",
337 | name: "RenderTime",
338 | type: "FLOAT",
339 | },
340 | {
341 | mode: "REQUIRED",
342 | name: "LoadTime",
343 | type: "INTEGER",
344 | },
345 | {
346 | mode: "REQUIRED",
347 | name: "ID",
348 | type: "STRING",
349 | },
350 | {
351 | mode: "REQUIRED",
352 | name: "URL",
353 | type: "STRING",
354 | },
355 | {
356 | mode: "REQUIRED",
357 | name: "Element",
358 | type: "STRING",
359 | },
360 | ],
361 | mode: "REPEATED",
362 | name: "Entries",
363 | type: "RECORD",
364 | },
365 | {
366 | mode: "REQUIRED",
367 | name: "ID",
368 | type: "STRING",
369 | },
370 | ],
371 | },
372 | TTFB: {
373 | fields: [
374 | {
375 | mode: "REQUIRED",
376 | name: "Name",
377 | type: "STRING",
378 | },
379 | {
380 | mode: "REQUIRED",
381 | name: "Value",
382 | type: "FLOAT",
383 | },
384 | {
385 | mode: "REQUIRED",
386 | name: "Delta",
387 | type: "FLOAT",
388 | },
389 | {
390 | fields: [
391 | {
392 | mode: "REQUIRED",
393 | name: "Name",
394 | type: "STRING",
395 | },
396 | {
397 | mode: "REQUIRED",
398 | name: "EntryType",
399 | type: "STRING",
400 | },
401 | {
402 | mode: "REQUIRED",
403 | name: "StartTime",
404 | type: "INTEGER",
405 | },
406 | {
407 | mode: "REQUIRED",
408 | name: "Duration",
409 | type: "FLOAT",
410 | },
411 | {
412 | mode: "REQUIRED",
413 | name: "InitiatorType",
414 | type: "STRING",
415 | },
416 | {
417 | mode: "REQUIRED",
418 | name: "NextHopProtocol",
419 | type: "STRING",
420 | },
421 | {
422 | mode: "REQUIRED",
423 | name: "WorkerStart",
424 | type: "INTEGER",
425 | },
426 | {
427 | mode: "REQUIRED",
428 | name: "RedirectStart",
429 | type: "INTEGER",
430 | },
431 | {
432 | mode: "REQUIRED",
433 | name: "RedirectEnd",
434 | type: "INTEGER",
435 | },
436 | {
437 | mode: "REQUIRED",
438 | name: "FetchStart",
439 | type: "FLOAT",
440 | },
441 | {
442 | mode: "REQUIRED",
443 | name: "DomainLookupStart",
444 | type: "FLOAT",
445 | },
446 | {
447 | mode: "REQUIRED",
448 | name: "DomainLookupEnd",
449 | type: "FLOAT",
450 | },
451 | {
452 | mode: "REQUIRED",
453 | name: "ConnectStart",
454 | type: "FLOAT",
455 | },
456 | {
457 | mode: "REQUIRED",
458 | name: "ConnectEnd",
459 | type: "FLOAT",
460 | },
461 | {
462 | mode: "REQUIRED",
463 | name: "SecureConnectionStart",
464 | type: "FLOAT",
465 | },
466 | {
467 | mode: "REQUIRED",
468 | name: "RequestStart",
469 | type: "FLOAT",
470 | },
471 | {
472 | mode: "REQUIRED",
473 | name: "ResponseStart",
474 | type: "FLOAT",
475 | },
476 | {
477 | mode: "REQUIRED",
478 | name: "ResponseEnd",
479 | type: "FLOAT",
480 | },
481 | {
482 | mode: "REQUIRED",
483 | name: "TransferSize",
484 | type: "INTEGER",
485 | },
486 | {
487 | mode: "REQUIRED",
488 | name: "EncodedBodySize",
489 | type: "INTEGER",
490 | },
491 | {
492 | mode: "REQUIRED",
493 | name: "DecodedBodySize",
494 | type: "INTEGER",
495 | },
496 | {
497 | mode: "REQUIRED",
498 | name: "UnloadEventStart",
499 | type: "FLOAT",
500 | },
501 | {
502 | mode: "REQUIRED",
503 | name: "UnloadEventEnd",
504 | type: "FLOAT",
505 | },
506 | {
507 | mode: "REQUIRED",
508 | name: "DomInteractive",
509 | type: "FLOAT",
510 | },
511 | {
512 | mode: "REQUIRED",
513 | name: "DomContentLoadedEventStart",
514 | type: "FLOAT",
515 | },
516 | {
517 | mode: "REQUIRED",
518 | name: "DomContentLoadedEventEnd",
519 | type: "FLOAT",
520 | },
521 | {
522 | mode: "REQUIRED",
523 | name: "DomComplete",
524 | type: "FLOAT",
525 | },
526 | {
527 | mode: "REQUIRED",
528 | name: "LoadEventStart",
529 | type: "FLOAT",
530 | },
531 | {
532 | mode: "REQUIRED",
533 | name: "LoadEventEnd",
534 | type: "FLOAT",
535 | },
536 | {
537 | mode: "REQUIRED",
538 | name: "Type",
539 | type: "STRING",
540 | },
541 | {
542 | mode: "REQUIRED",
543 | name: "RedirectCount",
544 | type: "INTEGER",
545 | },
546 | ],
547 | mode: "REPEATED",
548 | name: "Entries",
549 | type: "RECORD",
550 | },
551 | {
552 | mode: "REQUIRED",
553 | name: "ID",
554 | type: "STRING",
555 | },
556 | ],
557 | },
558 | };
559 |
--------------------------------------------------------------------------------
/packages/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es2015",
5 | "lib": ["ESNext", "DOM"],
6 | "declaration": true,
7 | "outDir": "./dist",
8 | "sourceMap": true,
9 | "rootDir": "./src",
10 | "strict": true,
11 | "noUnusedLocals": true,
12 | "noUnusedParameters": true,
13 | "noImplicitReturns": true,
14 | "noFallthroughCasesInSwitch": true,
15 | "downlevelIteration": true,
16 | "moduleResolution": "node",
17 | "esModuleInterop": true,
18 | "skipLibCheck": true,
19 | "forceConsistentCasingInFileNames": true,
20 | "isolatedModules": true,
21 | },
22 | "include": ["src", "types"],
23 | "exclude": ["node_modules"]
24 | }
--------------------------------------------------------------------------------
/packages/server/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@google-cloud/bigquery@^5.5.0":
6 | version "5.9.1"
7 | resolved "https://registry.yarnpkg.com/@google-cloud/bigquery/-/bigquery-5.9.1.tgz#96cee86fa0caef4a7e1470efde9295bc09f5981f"
8 | integrity sha512-80pMzhAC299CSiXW9TvR8AARLaPRDeQg8pSAvrVcLXcUkx1hWvVx2m94nBZ4KUoZb4LVWIHHYhvFB6XvIcxqjw==
9 | dependencies:
10 | "@google-cloud/common" "^3.1.0"
11 | "@google-cloud/paginator" "^3.0.0"
12 | "@google-cloud/promisify" "^2.0.0"
13 | arrify "^2.0.1"
14 | big.js "^6.0.0"
15 | duplexify "^4.0.0"
16 | extend "^3.0.2"
17 | is "^3.3.0"
18 | p-event "^4.1.0"
19 | stream-events "^1.0.5"
20 | uuid "^8.0.0"
21 |
22 | "@google-cloud/common@^3.1.0":
23 | version "3.8.1"
24 | resolved "https://registry.yarnpkg.com/@google-cloud/common/-/common-3.8.1.tgz#1313c55bb66df88f69bf7c828135fae25fbd2036"
25 | integrity sha512-FOs3NFU6bDt5mXE7IFpwIeqzLwRZNu9lJYl+bHVNkwmxX/w4VyDZAiGjQHhpV1Ek+muNKlX8HPchxaIxNTuOhw==
26 | dependencies:
27 | "@google-cloud/projectify" "^2.0.0"
28 | "@google-cloud/promisify" "^2.0.0"
29 | arrify "^2.0.1"
30 | duplexify "^4.1.1"
31 | ent "^2.2.0"
32 | extend "^3.0.2"
33 | google-auth-library "^7.9.2"
34 | retry-request "^4.2.2"
35 | teeny-request "^7.0.0"
36 |
37 | "@google-cloud/paginator@^3.0.0":
38 | version "3.0.6"
39 | resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-3.0.6.tgz#02a59dccd348d515069779a4f77a4a4fd15594da"
40 | integrity sha512-XCTm/GfQIlc1ZxpNtTSs/mnZxC2cePNhxU3X8EzHXKIJ2JFncmJj2Fcd2IP+gbmZaSZnY0juFxbUCkIeuu/2eQ==
41 | dependencies:
42 | arrify "^2.0.0"
43 | extend "^3.0.2"
44 |
45 | "@google-cloud/projectify@^2.0.0":
46 | version "2.1.1"
47 | resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-2.1.1.tgz#ae6af4fee02d78d044ae434699a630f8df0084ef"
48 | integrity sha512-+rssMZHnlh0twl122gXY4/aCrk0G1acBqkHFfYddtsqpYXGxA29nj9V5V9SfC+GyOG00l650f6lG9KL+EpFEWQ==
49 |
50 | "@google-cloud/promisify@^2.0.0":
51 | version "2.0.4"
52 | resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-2.0.4.tgz#9d8705ecb2baa41b6b2673f3a8e9b7b7e1abc52a"
53 | integrity sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA==
54 |
55 | "@tootallnate/once@2":
56 | version "2.0.0"
57 | resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
58 | integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
59 |
60 | "@types/node@^16.11.6":
61 | version "16.11.6"
62 | resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae"
63 | integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==
64 |
65 | abort-controller@^3.0.0:
66 | version "3.0.0"
67 | resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
68 | integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
69 | dependencies:
70 | event-target-shim "^5.0.0"
71 |
72 | agent-base@6:
73 | version "6.0.2"
74 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
75 | integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
76 | dependencies:
77 | debug "4"
78 |
79 | arrify@^2.0.0, arrify@^2.0.1:
80 | version "2.0.1"
81 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
82 | integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
83 |
84 | base64-js@^1.3.0:
85 | version "1.5.1"
86 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
87 | integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
88 |
89 | big.js@^6.0.0:
90 | version "6.1.1"
91 | resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.1.1.tgz#63b35b19dc9775c94991ee5db7694880655d5537"
92 | integrity sha512-1vObw81a8ylZO5ePrtMay0n018TcftpTA5HFKDaSuiUDBo8biRBtjIobw60OpwuvrGk+FsxKamqN4cnmj/eXdg==
93 |
94 | bignumber.js@^9.0.0:
95 | version "9.0.1"
96 | resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5"
97 | integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==
98 |
99 | buffer-equal-constant-time@1.0.1:
100 | version "1.0.1"
101 | resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
102 | integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
103 |
104 | debug@4, debug@^4.1.1:
105 | version "4.3.2"
106 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
107 | integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
108 | dependencies:
109 | ms "2.1.2"
110 |
111 | duplexify@^4.0.0, duplexify@^4.1.1:
112 | version "4.1.2"
113 | resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0"
114 | integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==
115 | dependencies:
116 | end-of-stream "^1.4.1"
117 | inherits "^2.0.3"
118 | readable-stream "^3.1.1"
119 | stream-shift "^1.0.0"
120 |
121 | ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11:
122 | version "1.0.11"
123 | resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
124 | integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
125 | dependencies:
126 | safe-buffer "^5.0.1"
127 |
128 | end-of-stream@^1.4.1:
129 | version "1.4.4"
130 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
131 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
132 | dependencies:
133 | once "^1.4.0"
134 |
135 | ent@^2.2.0:
136 | version "2.2.0"
137 | resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
138 | integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0=
139 |
140 | event-target-shim@^5.0.0:
141 | version "5.0.1"
142 | resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
143 | integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
144 |
145 | extend@^3.0.2:
146 | version "3.0.2"
147 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
148 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
149 |
150 | fast-text-encoding@^1.0.0:
151 | version "1.0.3"
152 | resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53"
153 | integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==
154 |
155 | gaxios@^4.0.0:
156 | version "4.3.2"
157 | resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-4.3.2.tgz#845827c2dc25a0213c8ab4155c7a28910f5be83f"
158 | integrity sha512-T+ap6GM6UZ0c4E6yb1y/hy2UB6hTrqhglp3XfmU9qbLCGRYhLVV5aRPpC4EmoG8N8zOnkYCgoBz+ScvGAARY6Q==
159 | dependencies:
160 | abort-controller "^3.0.0"
161 | extend "^3.0.2"
162 | https-proxy-agent "^5.0.0"
163 | is-stream "^2.0.0"
164 | node-fetch "^2.6.1"
165 |
166 | gcp-metadata@^4.2.0:
167 | version "4.3.1"
168 | resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.3.1.tgz#fb205fe6a90fef2fd9c85e6ba06e5559ee1eefa9"
169 | integrity sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==
170 | dependencies:
171 | gaxios "^4.0.0"
172 | json-bigint "^1.0.0"
173 |
174 | google-auth-library@^7.9.2:
175 | version "7.10.2"
176 | resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-7.10.2.tgz#7e48176f50e725e1d65b6a838ec9e9464e6ba689"
177 | integrity sha512-M37o9Kxa/TLvOLgF71SXvLeVEP5sbSTmKl1zlIgl72SFy5PtsU3pOdu8G8MIHHpQ3/NZabDI8rQkA9DvQVKkPA==
178 | dependencies:
179 | arrify "^2.0.0"
180 | base64-js "^1.3.0"
181 | ecdsa-sig-formatter "^1.0.11"
182 | fast-text-encoding "^1.0.0"
183 | gaxios "^4.0.0"
184 | gcp-metadata "^4.2.0"
185 | gtoken "^5.0.4"
186 | jws "^4.0.0"
187 | lru-cache "^6.0.0"
188 |
189 | google-p12-pem@^3.0.3:
190 | version "3.1.2"
191 | resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.1.2.tgz#c3d61c2da8e10843ff830fdb0d2059046238c1d4"
192 | integrity sha512-tjf3IQIt7tWCDsa0ofDQ1qqSCNzahXDxdAGJDbruWqu3eCg5CKLYKN+hi0s6lfvzYZ1GDVr+oDF9OOWlDSdf0A==
193 | dependencies:
194 | node-forge "^0.10.0"
195 |
196 | gtoken@^5.0.4:
197 | version "5.3.1"
198 | resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.3.1.tgz#c1c2598a826f2b5df7c6bb53d7be6cf6d50c3c78"
199 | integrity sha512-yqOREjzLHcbzz1UrQoxhBtpk8KjrVhuqPE7od1K2uhyxG2BHjKZetlbLw/SPZak/QqTIQW+addS+EcjqQsZbwQ==
200 | dependencies:
201 | gaxios "^4.0.0"
202 | google-p12-pem "^3.0.3"
203 | jws "^4.0.0"
204 |
205 | http-proxy-agent@^5.0.0:
206 | version "5.0.0"
207 | resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
208 | integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
209 | dependencies:
210 | "@tootallnate/once" "2"
211 | agent-base "6"
212 | debug "4"
213 |
214 | https-proxy-agent@^5.0.0:
215 | version "5.0.0"
216 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
217 | integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
218 | dependencies:
219 | agent-base "6"
220 | debug "4"
221 |
222 | inherits@^2.0.3:
223 | version "2.0.4"
224 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
225 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
226 |
227 | is-stream@^2.0.0:
228 | version "2.0.1"
229 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
230 | integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
231 |
232 | is@^3.3.0:
233 | version "3.3.0"
234 | resolved "https://registry.yarnpkg.com/is/-/is-3.3.0.tgz#61cff6dd3c4193db94a3d62582072b44e5645d79"
235 | integrity sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==
236 |
237 | json-bigint@^1.0.0:
238 | version "1.0.0"
239 | resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1"
240 | integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==
241 | dependencies:
242 | bignumber.js "^9.0.0"
243 |
244 | jwa@^2.0.0:
245 | version "2.0.0"
246 | resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc"
247 | integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==
248 | dependencies:
249 | buffer-equal-constant-time "1.0.1"
250 | ecdsa-sig-formatter "1.0.11"
251 | safe-buffer "^5.0.1"
252 |
253 | jws@^4.0.0:
254 | version "4.0.0"
255 | resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4"
256 | integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==
257 | dependencies:
258 | jwa "^2.0.0"
259 | safe-buffer "^5.0.1"
260 |
261 | lru-cache@^6.0.0:
262 | version "6.0.0"
263 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
264 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
265 | dependencies:
266 | yallist "^4.0.0"
267 |
268 | ms@2.1.2:
269 | version "2.1.2"
270 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
271 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
272 |
273 | node-fetch@^2.6.1:
274 | version "2.6.6"
275 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89"
276 | integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==
277 | dependencies:
278 | whatwg-url "^5.0.0"
279 |
280 | node-forge@^0.10.0:
281 | version "0.10.0"
282 | resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
283 | integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
284 |
285 | once@^1.4.0:
286 | version "1.4.0"
287 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
288 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
289 | dependencies:
290 | wrappy "1"
291 |
292 | p-event@^4.1.0:
293 | version "4.2.0"
294 | resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5"
295 | integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==
296 | dependencies:
297 | p-timeout "^3.1.0"
298 |
299 | p-finally@^1.0.0:
300 | version "1.0.0"
301 | resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
302 | integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
303 |
304 | p-timeout@^3.1.0:
305 | version "3.2.0"
306 | resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe"
307 | integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==
308 | dependencies:
309 | p-finally "^1.0.0"
310 |
311 | readable-stream@^3.1.1:
312 | version "3.6.0"
313 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
314 | integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
315 | dependencies:
316 | inherits "^2.0.3"
317 | string_decoder "^1.1.1"
318 | util-deprecate "^1.0.1"
319 |
320 | retry-request@^4.2.2:
321 | version "4.2.2"
322 | resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-4.2.2.tgz#b7d82210b6d2651ed249ba3497f07ea602f1a903"
323 | integrity sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg==
324 | dependencies:
325 | debug "^4.1.1"
326 | extend "^3.0.2"
327 |
328 | safe-buffer@^5.0.1, safe-buffer@~5.2.0:
329 | version "5.2.1"
330 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
331 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
332 |
333 | stream-events@^1.0.5:
334 | version "1.0.5"
335 | resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5"
336 | integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==
337 | dependencies:
338 | stubs "^3.0.0"
339 |
340 | stream-shift@^1.0.0:
341 | version "1.0.1"
342 | resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
343 | integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
344 |
345 | string_decoder@^1.1.1:
346 | version "1.3.0"
347 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
348 | integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
349 | dependencies:
350 | safe-buffer "~5.2.0"
351 |
352 | stubs@^3.0.0:
353 | version "3.0.0"
354 | resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b"
355 | integrity sha1-6NK6H6nJBXAwPAMLaQD31fiavls=
356 |
357 | teeny-request@^7.0.0:
358 | version "7.1.3"
359 | resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-7.1.3.tgz#5a3d90c559a6c664a993477b138e331a518765ba"
360 | integrity sha512-Ew3aoFzgQEatLA5OBIjdr1DWJUaC1xardG+qbPPo5k/y/3fMwXLxpjh5UB5dVfElktLaQbbMs80chkz53ByvSg==
361 | dependencies:
362 | http-proxy-agent "^5.0.0"
363 | https-proxy-agent "^5.0.0"
364 | node-fetch "^2.6.1"
365 | stream-events "^1.0.5"
366 | uuid "^8.0.0"
367 |
368 | tr46@~0.0.3:
369 | version "0.0.3"
370 | resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
371 | integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
372 |
373 | util-deprecate@^1.0.1:
374 | version "1.0.2"
375 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
376 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
377 |
378 | uuid@^8.0.0:
379 | version "8.3.2"
380 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
381 | integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
382 |
383 | webidl-conversions@^3.0.0:
384 | version "3.0.1"
385 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
386 | integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
387 |
388 | whatwg-url@^5.0.0:
389 | version "5.0.0"
390 | resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
391 | integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0=
392 | dependencies:
393 | tr46 "~0.0.3"
394 | webidl-conversions "^3.0.0"
395 |
396 | wrappy@1:
397 | version "1.0.2"
398 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
399 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
400 |
401 | yallist@^4.0.0:
402 | version "4.0.0"
403 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
404 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
405 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | tslib@^2.3.1:
6 | version "2.3.1"
7 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
8 | integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
9 |
--------------------------------------------------------------------------------