configure redis

This commit is contained in:
Brian Cao 2022-08-29 10:47:01 -07:00
parent efb52f5ff1
commit 48fe6ebcc5
13 changed files with 138 additions and 183 deletions

View File

@ -34,7 +34,7 @@ function getClient() {
});
if (process.env.NODE_ENV !== 'production') {
global[CLICKHOUSE] = clickhouse;
global[CLICKHOUSE] = client;
}
log('Clickhouse initialized');

View File

@ -1,22 +1,14 @@
import { createClient } from 'redis';
import Redis from 'ioredis';
import { startOfMonth } from 'date-fns';
import debug from 'debug';
// import debug from 'debug';
import { getSessions, getAllWebsites } from 'queries';
import { REDIS } from 'lib/db';
const log = debug('umami:redis');
// const log = debug('umami:redis');
const INITIALIZED = 'redis:initialized';
async function getClient() {
const redis = new createClient({
url: process.env.REDIS_URL,
});
await redis.connect();
if (process.env.LOG_QUERY) {
redis.on('error', err => log(err));
}
function getClient() {
const redis = new Redis(process.env.REDIS_URL);
if (process.env.NODE_ENV !== 'production') {
global[REDIS] = redis;
@ -26,11 +18,11 @@ async function getClient() {
}
async function stageData() {
const sessions = await getSessions([], startOfMonth(new Date()).toUTCString());
const sessions = await getSessions([], startOfMonth(new Date()));
const websites = await getAllWebsites();
const sessionUuids = sessions.map(a => {
return { key: `session:${a.session_uuid}`, value: '' };
return { key: `session:${a.session_uuid}`, value: 1 };
});
const websiteIds = websites.map(a => {
return { key: `website:${a.website_uuid}`, value: Number(a.website_id) };
@ -50,16 +42,12 @@ async function addRedis(ids) {
}
// Initialization
let redis = null;
const redis = process.env.REDIS_URL && (global[REDIS] || getClient());
(async () => {
redis = process.env.REDIS_URL && (global[REDIS] || (await getClient()));
if (redis) {
if (!(await redis.get(INITIALIZED))) {
await stageData();
}
if (!(await redis.get(INITIALIZED))) {
await stageData();
}
})();
export default redis;
export default { client: redis, stageData };

View File

@ -30,9 +30,11 @@ export async function getSession(req) {
let websiteId = null;
//console.log(await redis.stageData());
// Check if website exists
if (process.env.REDIS_URL) {
websiteId = await redis.get(`website:${website_uuid}`);
websiteId = await redis.client.get(`website:${website_uuid}`);
} else {
const { website_id } = await getWebsiteByUuid(website_uuid);
websiteId = website_id;
@ -52,7 +54,7 @@ export async function getSession(req) {
// Check if session exists
if (process.env.REDIS_URL) {
sessionCreated = (await redis.get(`session:${session_uuid}`)) !== null;
sessionCreated = !!(await redis.client.get(`session:${session_uuid}`));
} else {
session = await getSessionByUuid(session_uuid);
sessionCreated = !!session;
@ -61,7 +63,7 @@ export async function getSession(req) {
if (!sessionCreated) {
try {
session = await createSession(websiteId, {
session = await createSession(BigInt(websiteId), {
session_uuid,
hostname,
browser,

View File

@ -75,6 +75,7 @@
"formik": "^2.2.9",
"fs-extra": "^10.0.1",
"immer": "^9.0.12",
"ioredis": "^5.2.3",
"ipaddr.js": "^2.0.1",
"is-ci": "^3.0.1",
"is-docker": "^3.0.0",
@ -97,7 +98,6 @@
"react-tooltip": "^4.2.21",
"react-use-measure": "^2.0.4",
"react-window": "^1.8.6",
"redis": "^4.3.0",
"request-ip": "^3.3.0",
"semver": "^7.3.6",
"thenby": "^1.3.4",

View File

@ -14,7 +14,7 @@ export async function createWebsite(user_id, data) {
},
})
.then(async res => {
if (process.env.REDIS_URL) {
if (process.env.REDIS_URL && res) {
await redis.set(`website:${res.website_uuid}`, Number(res.website_id));
}

View File

@ -22,7 +22,7 @@ export async function deleteWebsite(website_id) {
}),
]).then(async res => {
if (process.env.REDIS_URL) {
await redis.del(`website:${res.website_uuid}`);
await redis.client.del(`website:${res.website_uuid}`);
}
});
}

View File

@ -1,9 +1,18 @@
import prisma from 'lib/prisma';
import redis from 'lib/redis';
export async function getWebsiteByUuid(website_uuid) {
return prisma.client.website.findUnique({
where: {
website_uuid,
},
});
return prisma.client.website
.findUnique({
where: {
website_uuid,
},
})
.then(async res => {
if (process.env.REDIS_URL && res) {
await redis.client.set(`website:${res.website_uuid}`, 1);
}
return res;
});
}

View File

@ -1,14 +1,12 @@
import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { EVENT_NAME_LENGTH, URL_LENGTH } from 'lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import kafka from 'lib/kafka';
import { runQuery, CLICKHOUSE, KAFKA, PRISMA } from 'lib/db';
import { URL_LENGTH, EVENT_NAME_LENGTH } from 'lib/constants';
import prisma from 'lib/prisma';
export async function saveEvent(...args) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
[KAFKA]: () => kafkaQuery(...args),
});
}
@ -34,23 +32,6 @@ async function relationalQuery(website_id, { session_id, url, event_name, event_
}
async function clickhouseQuery(website_id, { event_uuid, session_uuid, url, event_name }) {
const { rawQuery, getDateFormat } = clickhouse;
const params = [
website_id,
event_uuid,
session_uuid,
url?.substring(0, URL_LENGTH),
event_name?.substring(0, EVENT_NAME_LENGTH),
];
return rawQuery(
`insert into umami.event (created_at, website_id, session_uuid, url, event_name)
values (${getDateFormat(new Date())}, $1, $2, $3, $4);`,
params,
);
}
async function kafkaQuery(website_id, { event_uuid, session_uuid, url, event_name }) {
const { getDateFormat, sendMessage } = kafka;
const params = {
event_uuid: event_uuid,

View File

@ -1,14 +1,12 @@
import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import kafka from 'lib/kafka';
import { runQuery, CLICKHOUSE, KAFKA, PRISMA } from 'lib/db';
import { URL_LENGTH } from 'lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import kafka from 'lib/kafka';
import prisma from 'lib/prisma';
export async function savePageView(...args) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
[KAFKA]: () => kafkaQuery(...args),
});
}
@ -24,21 +22,6 @@ async function relationalQuery(website_id, { session_id, url, referrer }) {
}
async function clickhouseQuery(website_id, { session_uuid, url, referrer }) {
const params = [
website_id,
session_uuid,
url?.substring(0, URL_LENGTH),
referrer?.substring(0, URL_LENGTH),
];
return clickhouse.rawQuery(
`insert into umami.pageview (created_at, website_id, session_uuid, url, referrer)
values (${clickhouse.getDateFormat(new Date())}, $1, $2, $3, $4);`,
params,
);
}
async function kafkaQuery(website_id, { session_uuid, url, referrer }) {
const { getDateFormat, sendMessage } = kafka;
const params = {
website_id: website_id,

View File

@ -1,14 +1,12 @@
import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import kafka from 'lib/kafka';
import prisma from 'lib/prisma';
import redis from 'lib/redis';
import { runQuery, CLICKHOUSE, KAFKA, PRISMA } from 'lib/db';
export async function createSession(...args) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
[KAFKA]: () => kafkaQuery(...args),
});
}
@ -24,8 +22,8 @@ async function relationalQuery(website_id, data) {
},
})
.then(async res => {
if (process.env.REDIS_URL) {
await redis.set(`session:${res.session_uuid}`, '');
if (process.env.REDIS_URL && res) {
await redis.client.set(`session:${res.session_uuid}`, 1);
}
return res;
@ -35,30 +33,6 @@ async function relationalQuery(website_id, data) {
async function clickhouseQuery(
website_id,
{ session_uuid, hostname, browser, os, screen, language, country, device },
) {
const params = [
session_uuid,
website_id,
hostname,
browser,
os,
device,
screen,
language,
country ? country : null,
];
const { rawQuery, getDateFormat } = clickhouse;
await rawQuery(
`insert into umami.session (created_at, session_uuid, website_id, hostname, browser, os, device, screen, language, country)
values (${getDateFormat(new Date())}, $1, $2, $3, $4, $5, $6, $7, $8, $9);`,
params,
);
}
async function kafkaQuery(
website_id,
{ session_uuid, hostname, browser, os, screen, language, country, device },
) {
const { getDateFormat, sendMessage } = kafka;
const params = {
@ -76,5 +50,7 @@ async function kafkaQuery(
await sendMessage(params, 'session');
await redis.set(`session:${session_uuid}`, '');
if (process.env.REDIS_URL) {
await redis.client.set(`session:${session_uuid}`, 1);
}
}

View File

@ -1,6 +1,7 @@
import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import prisma from 'lib/prisma';
import redis from 'lib/redis';
export async function getSessionByUuid(...args) {
return runQuery({
@ -10,11 +11,19 @@ export async function getSessionByUuid(...args) {
}
async function relationalQuery(session_uuid) {
return prisma.client.session.findUnique({
where: {
session_uuid,
},
});
return prisma.client.session
.findUnique({
where: {
session_uuid,
},
})
.then(async res => {
if (process.env.REDIS_URL && res) {
await redis.client.set(`session:${res.session_uuid}`, 1);
}
return res;
});
}
async function clickhouseQuery(session_uuid) {
@ -36,5 +45,13 @@ async function clickhouseQuery(session_uuid) {
from session
where session_uuid = $1`,
params,
).then(result => findFirst(result));
)
.then(result => findFirst(result))
.then(async res => {
if (process.env.REDIS_URL && res) {
await redis.client.set(`session:${res.session_uuid}`, 1);
}
return res;
});
}

View File

@ -10,24 +10,22 @@ export async function getSessions(...args) {
}
async function relationalQuery(websites, start_at) {
return runQuery(
prisma.client.session.findMany({
where: {
...(websites && websites.length > 0
? {
website: {
website_id: {
in: websites,
},
return prisma.client.session.findMany({
where: {
...(websites && websites.length > 0
? {
website: {
website_id: {
in: websites,
},
}
: {}),
created_at: {
gte: start_at,
},
},
}
: {}),
created_at: {
gte: start_at,
},
}),
);
},
});
}
async function clickhouseQuery(websites, start_at) {

103
yarn.lock
View File

@ -1294,6 +1294,11 @@
resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz"
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@ioredis/commands@^1.1.1":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11"
integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==
"@jridgewell/gen-mapping@^0.1.0":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996"
@ -1543,40 +1548,6 @@
"@react-spring/shared" "~9.5.2"
"@react-spring/types" "~9.5.2"
"@redis/bloom@1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@redis/bloom/-/bloom-1.0.2.tgz#42b82ec399a92db05e29fffcdfd9235a5fc15cdf"
integrity sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw==
"@redis/client@1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@redis/client/-/client-1.3.0.tgz#c62ccd707f16370a2dc2f9e158a28b7da049fa77"
integrity sha512-XCFV60nloXAefDsPnYMjHGtvbtHR8fV5Om8cQ0JYqTNbWcQo/4AryzJ2luRj4blveWazRK/j40gES8M7Cp6cfQ==
dependencies:
cluster-key-slot "1.1.0"
generic-pool "3.8.2"
yallist "4.0.0"
"@redis/graph@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@redis/graph/-/graph-1.0.1.tgz#eabc58ba99cd70d0c907169c02b55497e4ec8a99"
integrity sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ==
"@redis/json@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@redis/json/-/json-1.0.3.tgz#a13fde1d22ebff0ae2805cd8e1e70522b08ea866"
integrity sha512-4X0Qv0BzD9Zlb0edkUoau5c1bInWSICqXAGrpwEltkncUwcxJIGEcVryZhLgb0p/3PkKaLIWkjhHRtLe9yiA7Q==
"@redis/search@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@redis/search/-/search-1.1.0.tgz#7abb18d431f27ceafe6bcb4dd83a3fa67e9ab4df"
integrity sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==
"@redis/time-series@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.3.tgz#4cfca8e564228c0bddcdf4418cba60c20b224ac4"
integrity sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==
"@rollup/plugin-buble@^0.21.3":
version "0.21.3"
resolved "https://registry.npmjs.org/@rollup/plugin-buble/-/plugin-buble-0.21.3.tgz"
@ -2514,7 +2485,7 @@ clickhouse@^2.5.0:
tsv "0.2.0"
uuid "3.4.0"
cluster-key-slot@1.1.0:
cluster-key-slot@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d"
integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==
@ -2946,6 +2917,11 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
denque@^2.0.1:
version "2.1.0"
resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1"
integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==
detect-browser@^5.2.0:
version "5.3.0"
resolved "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz"
@ -3631,11 +3607,6 @@ functions-have-names@^1.2.2:
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
generic-pool@3.8.2:
version "3.8.2"
resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.8.2.tgz#aab4f280adb522fdfbdc5e5b64d718d3683f04e9"
integrity sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==
gensync@^1.0.0-beta.2:
version "1.0.0-beta.2"
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
@ -3958,6 +3929,21 @@ intl-messageformat@9.13.0:
"@formatjs/icu-messageformat-parser" "2.1.0"
tslib "^2.1.0"
ioredis@^5.2.3:
version "5.2.3"
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.2.3.tgz#d5b37eb13e643241660d6cee4eeb41a026cda8c0"
integrity sha512-gQNcMF23/NpvjCaa1b5YycUyQJ9rBNH2xP94LWinNpodMWVUPP5Ai/xXANn/SM7gfIvI62B5CCvZxhg5pOgyMw==
dependencies:
"@ioredis/commands" "^1.1.1"
cluster-key-slot "^1.1.0"
debug "^4.3.4"
denque "^2.0.1"
lodash.defaults "^4.2.0"
lodash.isarguments "^3.1.0"
redis-errors "^1.2.0"
redis-parser "^3.0.0"
standard-as-callback "^2.1.0"
ipaddr.js@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz"
@ -4433,11 +4419,21 @@ lodash.debounce@^4.0.8:
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
lodash.defaults@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==
lodash.includes@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==
lodash.isarguments@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==
lodash.isboolean@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
@ -5649,17 +5645,17 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"
redis@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/redis/-/redis-4.3.0.tgz#c01de4cf13821406addb7fcb70afe203266c4c39"
integrity sha512-RXRUor0iU1vizu4viHoUyLpe1ZO/RngZp0V9DyXBHTI+7tC7rEz6Wzn4Sv9v0tTJeqGAzdJ+q5YVbNKKQ5hX9A==
redis-errors@^1.0.0, redis-errors@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad"
integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==
redis-parser@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4"
integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==
dependencies:
"@redis/bloom" "1.0.2"
"@redis/client" "1.3.0"
"@redis/graph" "1.0.1"
"@redis/json" "1.0.3"
"@redis/search" "1.1.0"
"@redis/time-series" "1.0.3"
redis-errors "^1.0.0"
redux@^4.0.0, redux@^4.0.4:
version "4.2.0"
@ -6135,6 +6131,11 @@ stable@^0.1.8:
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
standard-as-callback@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45"
integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==
stream2asynciter@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/stream2asynciter/-/stream2asynciter-1.0.3.tgz#7ba9046846c8b1caf36ec30d64a73514f7f44c5a"
@ -6809,7 +6810,7 @@ write-json-file@^4.3.0:
sort-keys "^4.0.0"
write-file-atomic "^3.0.0"
yallist@4.0.0, yallist@^4.0.0:
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==