diff --git a/lib/queries.js b/lib/queries.js index 0e93244e..a4188cf4 100644 --- a/lib/queries.js +++ b/lib/queries.js @@ -1,13 +1,6 @@ -import moment from 'moment-timezone'; +import { MYSQL, MYSQL_DATE_FORMATS, POSTGRESQL, POSTGRESQL_DATE_FORMATS } from 'lib/constants'; import prisma from 'lib/db'; -import { subMinutes } from 'date-fns'; -import { - MYSQL, - POSTGRESQL, - MYSQL_DATE_FORMATS, - POSTGRESQL_DATE_FORMATS, - URL_LENGTH, -} from 'lib/constants'; +import moment from 'moment-timezone'; export function getDatabase() { const type = @@ -148,455 +141,3 @@ export async function rawQuery(query, params = []) { return runQuery(prisma.$queryRawUnsafe.apply(prisma, [sql, ...params])); } - -export async function getWebsiteById(website_id) { - return runQuery( - prisma.website.findUnique({ - where: { - website_id, - }, - }), - ); -} - -export async function getWebsiteByUuid(website_uuid) { - return runQuery( - prisma.website.findUnique({ - where: { - website_uuid, - }, - }), - ); -} - -export async function getWebsiteByShareId(share_id) { - return runQuery( - prisma.website.findUnique({ - where: { - share_id, - }, - }), - ); -} - -export async function getUserWebsites(user_id) { - return runQuery( - prisma.website.findMany({ - where: { - user_id, - }, - orderBy: { - name: 'asc', - }, - }), - ); -} - -export async function getAllWebsites() { - let data = await runQuery( - prisma.website.findMany({ - orderBy: [ - { - user_id: 'asc', - }, - { - name: 'asc', - }, - ], - include: { - account: { - select: { - username: true, - }, - }, - }, - }), - ); - return data.map(i => ({ ...i, account: i.account.username })); -} - -export async function createWebsite(user_id, data) { - return runQuery( - prisma.website.create({ - data: { - account: { - connect: { - user_id, - }, - }, - ...data, - }, - }), - ); -} - -export async function updateWebsite(website_id, data) { - return runQuery( - prisma.website.update({ - where: { - website_id, - }, - data, - }), - ); -} - -export async function resetWebsite(website_id) { - return runQuery(prisma.$queryRaw`delete from session where website_id=${website_id}`); -} - -export async function deleteWebsite(website_id) { - return runQuery( - prisma.website.delete({ - where: { - website_id, - }, - }), - ); -} - -export async function createSession(website_id, data) { - return runQuery( - prisma.session.create({ - data: { - website_id, - ...data, - }, - select: { - session_id: true, - }, - }), - ); -} - -export async function getSessionByUuid(session_uuid) { - return runQuery( - prisma.session.findUnique({ - where: { - session_uuid, - }, - }), - ); -} - -export async function savePageView(website_id, session_id, url, referrer) { - return runQuery( - prisma.pageview.create({ - data: { - website_id, - session_id, - url: url?.substr(0, URL_LENGTH), - referrer: referrer?.substr(0, URL_LENGTH), - }, - }), - ); -} - -export async function saveEvent(website_id, session_id, url, event_type, event_value) { - return runQuery( - prisma.event.create({ - data: { - website_id, - session_id, - url: url?.substr(0, URL_LENGTH), - event_type: event_type?.substr(0, 50), - event_value: event_value?.substr(0, 50), - }, - }), - ); -} - -export async function getAccounts() { - return runQuery( - prisma.account.findMany({ - orderBy: [ - { is_admin: 'desc' }, - { - username: 'asc', - }, - ], - select: { - user_id: true, - username: true, - is_admin: true, - created_at: true, - updated_at: true, - }, - }), - ); -} - -export async function getAccountById(user_id) { - return runQuery( - prisma.account.findUnique({ - where: { - user_id, - }, - }), - ); -} - -export async function getAccountByUsername(username) { - return runQuery( - prisma.account.findUnique({ - where: { - username, - }, - }), - ); -} - -export async function updateAccount(user_id, data) { - return runQuery( - prisma.account.update({ - where: { - user_id, - }, - data, - }), - ); -} - -export async function deleteAccount(user_id) { - return runQuery( - prisma.account.delete({ - where: { - user_id, - }, - }), - ); -} - -export async function createAccount(data) { - return runQuery( - prisma.account.create({ - data, - }), - ); -} - -export async function getSessions(websites, start_at) { - return runQuery( - prisma.session.findMany({ - where: { - website: { - website_id: { - in: websites, - }, - }, - created_at: { - gte: start_at, - }, - }, - }), - ); -} - -export async function getPageviews(websites, start_at) { - return runQuery( - prisma.pageview.findMany({ - where: { - website: { - website_id: { - in: websites, - }, - }, - created_at: { - gte: start_at, - }, - }, - }), - ); -} - -export async function getEvents(websites, start_at) { - return runQuery( - prisma.event.findMany({ - where: { - website: { - website_id: { - in: websites, - }, - }, - created_at: { - gte: start_at, - }, - }, - }), - ); -} - -export function getWebsiteStats(website_id, start_at, end_at, filters = {}) { - const params = [website_id, start_at, end_at]; - const { pageviewQuery, sessionQuery, joinSession } = parseFilters('pageview', filters, params); - - return rawQuery( - ` - select sum(t.c) as "pageviews", - count(distinct t.session_id) as "uniques", - sum(case when t.c = 1 then 1 else 0 end) as "bounces", - sum(t.time) as "totaltime" - from ( - select pageview.session_id, - ${getDateQuery('pageview.created_at', 'hour')}, - count(*) c, - ${getTimestampInterval('pageview.created_at')} as "time" - from pageview - ${joinSession} - where pageview.website_id=$1 - and pageview.created_at between $2 and $3 - ${pageviewQuery} - ${sessionQuery} - group by 1, 2 - ) t - `, - params, - ); -} - -export function getPageviewStats( - website_id, - start_at, - end_at, - timezone = 'utc', - unit = 'day', - count = '*', - filters = {}, -) { - const params = [website_id, start_at, end_at]; - const { pageviewQuery, sessionQuery, joinSession } = parseFilters('pageview', filters, params); - - return rawQuery( - ` - select ${getDateQuery('pageview.created_at', unit, timezone)} t, - count(${count}) y - from pageview - ${joinSession} - where pageview.website_id=$1 - and pageview.created_at between $2 and $3 - ${pageviewQuery} - ${sessionQuery} - group by 1 - order by 1 - `, - params, - ); -} - -export function getSessionMetrics(website_id, start_at, end_at, field, filters = {}) { - const params = [website_id, start_at, end_at]; - const { pageviewQuery, sessionQuery, joinSession } = parseFilters('pageview', filters, params); - - return rawQuery( - ` - select ${field} x, count(*) y - from session as x - where x.session_id in ( - select pageview.session_id - from pageview - ${joinSession} - where pageview.website_id=$1 - and pageview.created_at between $2 and $3 - ${pageviewQuery} - ${sessionQuery} - ) - group by 1 - order by 2 desc - `, - params, - ); -} - -export function getPageviewMetrics(website_id, start_at, end_at, field, table, filters = {}) { - const params = [website_id, start_at, end_at]; - const { pageviewQuery, sessionQuery, eventQuery, joinSession } = parseFilters( - table, - filters, - params, - ); - - return rawQuery( - ` - select ${field} x, count(*) y - from ${table} - ${joinSession} - where ${table}.website_id=$1 - and ${table}.created_at between $2 and $3 - ${pageviewQuery} - ${joinSession && sessionQuery} - ${eventQuery} - group by 1 - order by 2 desc - `, - params, - ); -} - -export function getActiveVisitors(website_id) { - const date = subMinutes(new Date(), 5); - const params = [website_id, date]; - - return rawQuery( - ` - select count(distinct session_id) x - from pageview - where website_id=$1 - and created_at >= $2 - `, - params, - ); -} - -export function getEventMetrics( - website_id, - start_at, - end_at, - timezone = 'utc', - unit = 'day', - filters = {}, -) { - const params = [website_id, start_at, end_at]; - - return rawQuery( - ` - select - event_value x, - ${getDateQuery('created_at', unit, timezone)} t, - count(*) y - from event - where website_id=$1 - and created_at between $2 and $3 - ${getFilterQuery('event', filters, params)} - group by 1, 2 - order by 2 - `, - params, - ); -} - -export async function getRealtimeData(websites, time) { - const [pageviews, sessions, events] = await Promise.all([ - getPageviews(websites, time), - getSessions(websites, time), - getEvents(websites, time), - ]); - - return { - pageviews: pageviews.map(({ view_id, ...props }) => ({ - __id: `p${view_id}`, - view_id, - ...props, - })), - sessions: sessions.map(({ session_id, ...props }) => ({ - __id: `s${session_id}`, - session_id, - ...props, - })), - events: events.map(({ event_id, ...props }) => ({ - __id: `e${event_id}`, - event_id, - ...props, - })), - timestamp: Date.now(), - }; -} diff --git a/lib/session.js b/lib/session.js index a08eec79..15a349fd 100644 --- a/lib/session.js +++ b/lib/session.js @@ -1,4 +1,4 @@ -import { getWebsiteByUuid, getSessionByUuid, createSession } from 'lib/queries'; +import { getWebsiteByUuid, getSessionByUuid, createSession } from 'queries'; import { getJsonBody, getClientInfo } from 'lib/request'; import { uuid, isValidUuid, parseToken } from 'lib/crypto'; diff --git a/pages/api/account/[id].js b/pages/api/account/[id].js index 6f9beac1..51279f4b 100644 --- a/pages/api/account/[id].js +++ b/pages/api/account/[id].js @@ -1,4 +1,4 @@ -import { getAccountById, deleteAccount } from 'lib/queries'; +import { getAccountById, deleteAccount } from 'queries'; import { useAuth } from 'lib/middleware'; import { methodNotAllowed, ok, unauthorized } from 'lib/response'; diff --git a/pages/api/account/index.js b/pages/api/account/index.js index 5afd8212..a7cb3795 100644 --- a/pages/api/account/index.js +++ b/pages/api/account/index.js @@ -1,4 +1,4 @@ -import { getAccountById, getAccountByUsername, updateAccount, createAccount } from 'lib/queries'; +import { getAccountById, getAccountByUsername, updateAccount, createAccount } from 'queries'; import { useAuth } from 'lib/middleware'; import { hashPassword } from 'lib/crypto'; import { ok, unauthorized, methodNotAllowed, badRequest } from 'lib/response'; diff --git a/pages/api/account/password.js b/pages/api/account/password.js index 39068c7f..432ba34c 100644 --- a/pages/api/account/password.js +++ b/pages/api/account/password.js @@ -1,4 +1,4 @@ -import { getAccountById, updateAccount } from 'lib/queries'; +import { getAccountById, updateAccount } from 'queries'; import { useAuth } from 'lib/middleware'; import { badRequest, methodNotAllowed, ok, unauthorized } from 'lib/response'; import { checkPassword, hashPassword } from 'lib/crypto'; diff --git a/pages/api/accounts/index.js b/pages/api/accounts/index.js index 3d651601..29edf828 100644 --- a/pages/api/accounts/index.js +++ b/pages/api/accounts/index.js @@ -1,4 +1,4 @@ -import { getAccounts } from 'lib/queries'; +import { getAccounts } from 'queries'; import { useAuth } from 'lib/middleware'; import { ok, unauthorized, methodNotAllowed } from 'lib/response'; diff --git a/pages/api/auth/login.js b/pages/api/auth/login.js index 11d81ba6..9a4aed9e 100644 --- a/pages/api/auth/login.js +++ b/pages/api/auth/login.js @@ -1,5 +1,5 @@ import { checkPassword, createSecureToken } from 'lib/crypto'; -import { getAccountByUsername } from 'lib/queries'; +import { getAccountByUsername } from 'queries/admin/account/getAccountByUsername'; import { ok, unauthorized, badRequest } from 'lib/response'; export default async (req, res) => { diff --git a/pages/api/collect.js b/pages/api/collect.js index 3387cde1..acd031a9 100644 --- a/pages/api/collect.js +++ b/pages/api/collect.js @@ -1,7 +1,7 @@ const { Resolver } = require('dns').promises; import isbot from 'isbot'; import ipaddr from 'ipaddr.js'; -import { savePageView, saveEvent } from 'lib/queries'; +import { savePageView, saveEvent } from 'queries'; import { useCors, useSession } from 'lib/middleware'; import { getJsonBody, getIpAddress } from 'lib/request'; import { ok, send, badRequest, forbidden } from 'lib/response'; diff --git a/pages/api/realtime/init.js b/pages/api/realtime/init.js index 52e66600..69c70a82 100644 --- a/pages/api/realtime/init.js +++ b/pages/api/realtime/init.js @@ -1,7 +1,7 @@ import { subMinutes } from 'date-fns'; import { useAuth } from 'lib/middleware'; import { ok, methodNotAllowed } from 'lib/response'; -import { getUserWebsites, getRealtimeData } from 'lib/queries'; +import { getUserWebsites, getRealtimeData } from 'queries'; import { createToken } from 'lib/crypto'; export default async (req, res) => { diff --git a/pages/api/realtime/update.js b/pages/api/realtime/update.js index a43d7b66..4fa0ea3b 100644 --- a/pages/api/realtime/update.js +++ b/pages/api/realtime/update.js @@ -1,6 +1,6 @@ import { useAuth } from 'lib/middleware'; import { ok, methodNotAllowed, badRequest } from 'lib/response'; -import { getRealtimeData } from 'lib/queries'; +import { getRealtimeData } from 'queries'; import { parseToken } from 'lib/crypto'; import { SHARE_TOKEN_HEADER } from 'lib/constants'; diff --git a/pages/api/share/[id].js b/pages/api/share/[id].js index 461e008e..698f1ba0 100644 --- a/pages/api/share/[id].js +++ b/pages/api/share/[id].js @@ -1,4 +1,4 @@ -import { getWebsiteByShareId } from 'lib/queries'; +import { getWebsiteByShareId } from 'queries'; import { ok, notFound, methodNotAllowed } from 'lib/response'; import { createToken } from 'lib/crypto'; diff --git a/pages/api/website/[id]/active.js b/pages/api/website/[id]/active.js index ad7f8991..4acc97f1 100644 --- a/pages/api/website/[id]/active.js +++ b/pages/api/website/[id]/active.js @@ -1,7 +1,7 @@ -import { getActiveVisitors } from 'lib/queries'; import { methodNotAllowed, ok, unauthorized } from 'lib/response'; import { allowQuery } from 'lib/auth'; import { useCors } from 'lib/middleware'; +import { getActiveVisitors } from 'queries'; export default async (req, res) => { if (req.method === 'GET') { diff --git a/pages/api/website/[id]/events.js b/pages/api/website/[id]/events.js index 974e79f3..34e5f659 100644 --- a/pages/api/website/[id]/events.js +++ b/pages/api/website/[id]/events.js @@ -1,5 +1,5 @@ import moment from 'moment-timezone'; -import { getEventMetrics } from 'lib/queries'; +import { getEventMetrics } from 'queries/analytics'; import { ok, badRequest, methodNotAllowed, unauthorized } from 'lib/response'; import { allowQuery } from 'lib/auth'; import { useCors } from 'lib/middleware'; diff --git a/pages/api/website/[id]/index.js b/pages/api/website/[id]/index.js index 7018a01d..048b5ff1 100644 --- a/pages/api/website/[id]/index.js +++ b/pages/api/website/[id]/index.js @@ -1,4 +1,4 @@ -import { deleteWebsite, getWebsiteById } from 'lib/queries'; +import { deleteWebsite, getWebsiteById } from 'queries'; import { methodNotAllowed, ok, unauthorized } from 'lib/response'; import { allowQuery } from 'lib/auth'; import { useCors } from 'lib/middleware'; diff --git a/pages/api/website/[id]/metrics.js b/pages/api/website/[id]/metrics.js index 54c5bf3e..3fb33f88 100644 --- a/pages/api/website/[id]/metrics.js +++ b/pages/api/website/[id]/metrics.js @@ -1,4 +1,4 @@ -import { getPageviewMetrics, getSessionMetrics, getWebsiteById } from 'lib/queries'; +import { getPageviewMetrics, getSessionMetrics, getWebsiteById } from 'queries'; import { ok, methodNotAllowed, unauthorized, badRequest } from 'lib/response'; import { allowQuery } from 'lib/auth'; import { useCors } from 'lib/middleware'; diff --git a/pages/api/website/[id]/pageviews.js b/pages/api/website/[id]/pageviews.js index bc663ce1..78145e8b 100644 --- a/pages/api/website/[id]/pageviews.js +++ b/pages/api/website/[id]/pageviews.js @@ -1,5 +1,5 @@ import moment from 'moment-timezone'; -import { getPageviewStats } from 'lib/queries'; +import { getPageviewStats } from 'queries'; import { ok, badRequest, methodNotAllowed, unauthorized } from 'lib/response'; import { allowQuery } from 'lib/auth'; import { useCors } from 'lib/middleware'; diff --git a/pages/api/website/[id]/reset.js b/pages/api/website/[id]/reset.js index 2830ccc8..10fc5cb7 100644 --- a/pages/api/website/[id]/reset.js +++ b/pages/api/website/[id]/reset.js @@ -1,4 +1,4 @@ -import { resetWebsite } from 'lib/queries'; +import { resetWebsite } from 'queries'; import { methodNotAllowed, ok, unauthorized } from 'lib/response'; import { allowQuery } from 'lib/auth'; diff --git a/pages/api/website/[id]/stats.js b/pages/api/website/[id]/stats.js index 15cc45ad..7f37574c 100644 --- a/pages/api/website/[id]/stats.js +++ b/pages/api/website/[id]/stats.js @@ -1,4 +1,4 @@ -import { getWebsiteStats } from 'lib/queries'; +import { getWebsiteStats } from 'queries'; import { methodNotAllowed, ok, unauthorized } from 'lib/response'; import { allowQuery } from 'lib/auth'; import { useCors } from 'lib/middleware'; diff --git a/pages/api/website/index.js b/pages/api/website/index.js index dab9a94d..59d0a5f1 100644 --- a/pages/api/website/index.js +++ b/pages/api/website/index.js @@ -1,4 +1,4 @@ -import { updateWebsite, createWebsite, getWebsiteById } from 'lib/queries'; +import { updateWebsite, createWebsite, getWebsiteById } from 'queries'; import { useAuth } from 'lib/middleware'; import { uuid, getRandomChars } from 'lib/crypto'; import { ok, unauthorized, methodNotAllowed } from 'lib/response'; diff --git a/pages/api/websites/index.js b/pages/api/websites/index.js index 589b7315..b70272d8 100644 --- a/pages/api/websites/index.js +++ b/pages/api/websites/index.js @@ -1,4 +1,4 @@ -import { getAllWebsites, getUserWebsites } from 'lib/queries'; +import { getAllWebsites, getUserWebsites } from 'queries'; import { useAuth } from 'lib/middleware'; import { ok, methodNotAllowed, unauthorized } from 'lib/response'; diff --git a/queries/admin/account/createAccount.js b/queries/admin/account/createAccount.js new file mode 100644 index 00000000..577bc769 --- /dev/null +++ b/queries/admin/account/createAccount.js @@ -0,0 +1,10 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function createAccount(data) { + return runQuery( + prisma.account.create({ + data, + }), + ); +} diff --git a/queries/admin/account/deleteAccount.js b/queries/admin/account/deleteAccount.js new file mode 100644 index 00000000..7a9d66f9 --- /dev/null +++ b/queries/admin/account/deleteAccount.js @@ -0,0 +1,12 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function deleteAccount(user_id) { + return runQuery( + prisma.account.delete({ + where: { + user_id, + }, + }), + ); +} diff --git a/queries/admin/account/getAccountById.js b/queries/admin/account/getAccountById.js new file mode 100644 index 00000000..317734b8 --- /dev/null +++ b/queries/admin/account/getAccountById.js @@ -0,0 +1,12 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function getAccountById(user_id) { + return runQuery( + prisma.account.findUnique({ + where: { + user_id, + }, + }), + ); +} diff --git a/queries/admin/account/getAccountByUsername.js b/queries/admin/account/getAccountByUsername.js new file mode 100644 index 00000000..82e9ab53 --- /dev/null +++ b/queries/admin/account/getAccountByUsername.js @@ -0,0 +1,12 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function getAccountByUsername(username) { + return runQuery( + prisma.account.findUnique({ + where: { + username, + }, + }), + ); +} diff --git a/queries/admin/account/getAccounts.js b/queries/admin/account/getAccounts.js new file mode 100644 index 00000000..651d6784 --- /dev/null +++ b/queries/admin/account/getAccounts.js @@ -0,0 +1,22 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function getAccounts() { + return runQuery( + prisma.account.findMany({ + orderBy: [ + { is_admin: 'desc' }, + { + username: 'asc', + }, + ], + select: { + user_id: true, + username: true, + is_admin: true, + created_at: true, + updated_at: true, + }, + }), + ); +} diff --git a/queries/admin/account/updateAccount.js b/queries/admin/account/updateAccount.js new file mode 100644 index 00000000..0904497b --- /dev/null +++ b/queries/admin/account/updateAccount.js @@ -0,0 +1,13 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function updateAccount(user_id, data) { + return runQuery( + prisma.account.update({ + where: { + user_id, + }, + data, + }), + ); +} diff --git a/queries/admin/index.js b/queries/admin/index.js new file mode 100644 index 00000000..37ca9991 --- /dev/null +++ b/queries/admin/index.js @@ -0,0 +1,33 @@ +import { createAccount } from './account/createAccount'; +import { deleteAccount } from './account/deleteAccount'; +import { getAccountById } from './account/getAccountById'; +import { getAccountByUsername } from './account/getAccountByUsername'; +import { getAccounts } from './account/getAccounts'; +import { updateAccount } from './account/updateAccount'; +import { createWebsite } from './website/createWebsite'; +import { deleteWebsite } from './website/deleteWebsite'; +import { getAllWebsites } from './website/getAllWebsites'; +import { getUserWebsites } from './website/getUserWebsites'; +import { getWebsiteById } from './website/getWebsiteById'; +import { getWebsiteByShareId } from './website/getWebsiteByShareId'; +import { getWebsiteByUuid } from './website/getWebsiteByUuid'; +import { resetWebsite } from './website/resetWebsite'; +import { updateWebsite } from './website/updateWebsite'; + +export default { + createWebsite, + deleteWebsite, + getAllWebsites, + getUserWebsites, + getWebsiteById, + getWebsiteByShareId, + getWebsiteByUuid, + resetWebsite, + updateWebsite, + createAccount, + deleteAccount, + getAccountById, + getAccountByUsername, + getAccounts, + updateAccount, +}; diff --git a/queries/admin/website/createWebsite.js b/queries/admin/website/createWebsite.js new file mode 100644 index 00000000..21cfda85 --- /dev/null +++ b/queries/admin/website/createWebsite.js @@ -0,0 +1,17 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function createWebsite(user_id, data) { + return runQuery( + prisma.website.create({ + data: { + account: { + connect: { + user_id, + }, + }, + ...data, + }, + }), + ); +} diff --git a/queries/admin/website/deleteWebsite.js b/queries/admin/website/deleteWebsite.js new file mode 100644 index 00000000..d111da8f --- /dev/null +++ b/queries/admin/website/deleteWebsite.js @@ -0,0 +1,12 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function deleteWebsite(website_id) { + return runQuery( + prisma.website.delete({ + where: { + website_id, + }, + }), + ); +} diff --git a/queries/admin/website/getAllWebsites.js b/queries/admin/website/getAllWebsites.js new file mode 100644 index 00000000..0d326b95 --- /dev/null +++ b/queries/admin/website/getAllWebsites.js @@ -0,0 +1,25 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function getAllWebsites() { + let data = await runQuery( + prisma.website.findMany({ + orderBy: [ + { + user_id: 'asc', + }, + { + name: 'asc', + }, + ], + include: { + account: { + select: { + username: true, + }, + }, + }, + }), + ); + return data.map(i => ({ ...i, account: i.account.username })); +} diff --git a/queries/admin/website/getUserWebsites.js b/queries/admin/website/getUserWebsites.js new file mode 100644 index 00000000..2fb1153f --- /dev/null +++ b/queries/admin/website/getUserWebsites.js @@ -0,0 +1,15 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function getUserWebsites(user_id) { + return runQuery( + prisma.website.findMany({ + where: { + user_id, + }, + orderBy: { + name: 'asc', + }, + }), + ); +} diff --git a/queries/admin/website/getWebsiteById.js b/queries/admin/website/getWebsiteById.js new file mode 100644 index 00000000..d49157de --- /dev/null +++ b/queries/admin/website/getWebsiteById.js @@ -0,0 +1,12 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function getWebsiteById(website_id) { + return runQuery( + prisma.website.findUnique({ + where: { + website_id, + }, + }), + ); +} diff --git a/queries/admin/website/getWebsiteByShareId.js b/queries/admin/website/getWebsiteByShareId.js new file mode 100644 index 00000000..a3d36cb1 --- /dev/null +++ b/queries/admin/website/getWebsiteByShareId.js @@ -0,0 +1,12 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function getWebsiteByShareId(share_id) { + return runQuery( + prisma.website.findUnique({ + where: { + share_id, + }, + }), + ); +} diff --git a/queries/admin/website/getWebsiteByUuid.js b/queries/admin/website/getWebsiteByUuid.js new file mode 100644 index 00000000..7ac04f6c --- /dev/null +++ b/queries/admin/website/getWebsiteByUuid.js @@ -0,0 +1,12 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function getWebsiteByUuid(website_uuid) { + return runQuery( + prisma.website.findUnique({ + where: { + website_uuid, + }, + }), + ); +} diff --git a/queries/admin/website/resetWebsite.js b/queries/admin/website/resetWebsite.js new file mode 100644 index 00000000..0d7cb3d0 --- /dev/null +++ b/queries/admin/website/resetWebsite.js @@ -0,0 +1,6 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function resetWebsite(website_id) { + return runQuery(prisma.$queryRaw`delete from session where website_id=${website_id}`); +} diff --git a/queries/admin/website/updateWebsite.js b/queries/admin/website/updateWebsite.js new file mode 100644 index 00000000..4a6a4742 --- /dev/null +++ b/queries/admin/website/updateWebsite.js @@ -0,0 +1,13 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function updateWebsite(website_id, data) { + return runQuery( + prisma.website.update({ + where: { + website_id, + }, + data, + }), + ); +} diff --git a/queries/analytics/event/getEventMetrics.js b/queries/analytics/event/getEventMetrics.js new file mode 100644 index 00000000..674059be --- /dev/null +++ b/queries/analytics/event/getEventMetrics.js @@ -0,0 +1,28 @@ +import { getDateQuery, getFilterQuery, rawQuery } from 'queries'; + +export function getEventMetrics( + website_id, + start_at, + end_at, + timezone = 'utc', + unit = 'day', + filters = {}, +) { + const params = [website_id, start_at, end_at]; + + return rawQuery( + ` + select + event_value x, + ${getDateQuery('created_at', unit, timezone)} t, + count(*) y + from event + where website_id=$1 + and created_at between $2 and $3 + ${getFilterQuery('event', filters, params)} + group by 1, 2 + order by 2 + `, + params, + ); +} diff --git a/queries/analytics/event/getEvents.js b/queries/analytics/event/getEvents.js new file mode 100644 index 00000000..2914f45a --- /dev/null +++ b/queries/analytics/event/getEvents.js @@ -0,0 +1,19 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function getEvents(websites, start_at) { + return runQuery( + prisma.event.findMany({ + where: { + website: { + website_id: { + in: websites, + }, + }, + created_at: { + gte: start_at, + }, + }, + }), + ); +} diff --git a/queries/analytics/event/saveEvent.js b/queries/analytics/event/saveEvent.js new file mode 100644 index 00000000..7314f994 --- /dev/null +++ b/queries/analytics/event/saveEvent.js @@ -0,0 +1,17 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; +import { URL_LENGTH } from 'lib/constants'; + +export async function saveEvent(website_id, session_id, url, event_type, event_value) { + return runQuery( + prisma.event.create({ + data: { + website_id, + session_id, + url: url?.substr(0, URL_LENGTH), + event_type: event_type?.substr(0, 50), + event_value: event_value?.substr(0, 50), + }, + }), + ); +} diff --git a/queries/analytics/index.js b/queries/analytics/index.js new file mode 100644 index 00000000..c1937935 --- /dev/null +++ b/queries/analytics/index.js @@ -0,0 +1,31 @@ +import { getEventMetrics } from './event/getEventMetrics'; +import { getEvents } from './event/getEvents'; +import { saveEvent } from './event/saveEvent'; +import { getPageviewMetrics } from './pageview/getPageviewMetrics'; +import { getPageviews } from './pageview/getPageviews'; +import { getPageviewStats } from './pageview/getPageviewStats'; +import { savePageView } from './pageview/savePageView'; +import { createSession } from './session/createSession'; +import { getSessionByUuid } from './session/getSessionByUuid'; +import { getSessionMetrics } from './session/getSessionMetrics'; +import { getSessions } from './session/getSessions'; +import { getActiveVisitors } from './stats/getActiveVisitors'; +import { getRealtimeData } from './stats/getRealtimeData'; +import { getWebsiteStats } from './stats/getWebsiteStats'; + +export default { + getEventMetrics, + getEvents, + saveEvent, + getPageviewMetrics, + getPageviews, + getPageviewStats, + savePageView, + createSession, + getSessionByUuid, + getSessionMetrics, + getSessions, + getActiveVisitors, + getRealtimeData, + getWebsiteStats, +}; diff --git a/queries/analytics/pageview/getPageviewMetrics.js b/queries/analytics/pageview/getPageviewMetrics.js new file mode 100644 index 00000000..4a3214cc --- /dev/null +++ b/queries/analytics/pageview/getPageviewMetrics.js @@ -0,0 +1,26 @@ +import { parseFilters, rawQuery } from 'queries'; + +export function getPageviewMetrics(website_id, start_at, end_at, field, table, filters = {}) { + const params = [website_id, start_at, end_at]; + const { pageviewQuery, sessionQuery, eventQuery, joinSession } = parseFilters( + table, + filters, + params, + ); + + return rawQuery( + ` + select ${field} x, count(*) y + from ${table} + ${joinSession} + where ${table}.website_id=$1 + and ${table}.created_at between $2 and $3 + ${pageviewQuery} + ${joinSession && sessionQuery} + ${eventQuery} + group by 1 + order by 2 desc + `, + params, + ); +} diff --git a/queries/analytics/pageview/getPageviewStats.js b/queries/analytics/pageview/getPageviewStats.js new file mode 100644 index 00000000..f6bb6657 --- /dev/null +++ b/queries/analytics/pageview/getPageviewStats.js @@ -0,0 +1,30 @@ +import { parseFilters, rawQuery, getDateQuery } from 'queries'; + +export function getPageviewStats( + website_id, + start_at, + end_at, + timezone = 'utc', + unit = 'day', + count = '*', + filters = {}, +) { + const params = [website_id, start_at, end_at]; + const { pageviewQuery, sessionQuery, joinSession } = parseFilters('pageview', filters, params); + + return rawQuery( + ` + select ${getDateQuery('pageview.created_at', unit, timezone)} t, + count(${count}) y + from pageview + ${joinSession} + where pageview.website_id=$1 + and pageview.created_at between $2 and $3 + ${pageviewQuery} + ${sessionQuery} + group by 1 + order by 1 + `, + params, + ); +} diff --git a/queries/analytics/pageview/getPageviews.js b/queries/analytics/pageview/getPageviews.js new file mode 100644 index 00000000..de450ea3 --- /dev/null +++ b/queries/analytics/pageview/getPageviews.js @@ -0,0 +1,19 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function getPageviews(websites, start_at) { + return runQuery( + prisma.pageview.findMany({ + where: { + website: { + website_id: { + in: websites, + }, + }, + created_at: { + gte: start_at, + }, + }, + }), + ); +} diff --git a/queries/analytics/pageview/savePageView.js b/queries/analytics/pageview/savePageView.js new file mode 100644 index 00000000..e541e34e --- /dev/null +++ b/queries/analytics/pageview/savePageView.js @@ -0,0 +1,16 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; +import { URL_LENGTH } from 'lib/constants'; + +export async function savePageView(website_id, session_id, url, referrer) { + return runQuery( + prisma.pageview.create({ + data: { + website_id, + session_id, + url: url?.substr(0, URL_LENGTH), + referrer: referrer?.substr(0, URL_LENGTH), + }, + }), + ); +} diff --git a/queries/analytics/session/createSession.js b/queries/analytics/session/createSession.js new file mode 100644 index 00000000..79671a9c --- /dev/null +++ b/queries/analytics/session/createSession.js @@ -0,0 +1,16 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function createSession(website_id, data) { + return runQuery( + prisma.session.create({ + data: { + website_id, + ...data, + }, + select: { + session_id: true, + }, + }), + ); +} diff --git a/queries/analytics/session/getSessionByUuid.js b/queries/analytics/session/getSessionByUuid.js new file mode 100644 index 00000000..33823c4f --- /dev/null +++ b/queries/analytics/session/getSessionByUuid.js @@ -0,0 +1,12 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function getSessionByUuid(session_uuid) { + return runQuery( + prisma.session.findUnique({ + where: { + session_uuid, + }, + }), + ); +} diff --git a/queries/analytics/session/getSessionMetrics.js b/queries/analytics/session/getSessionMetrics.js new file mode 100644 index 00000000..16858cf1 --- /dev/null +++ b/queries/analytics/session/getSessionMetrics.js @@ -0,0 +1,25 @@ +import { parseFilters, rawQuery } from 'queries'; + +export function getSessionMetrics(website_id, start_at, end_at, field, filters = {}) { + const params = [website_id, start_at, end_at]; + const { pageviewQuery, sessionQuery, joinSession } = parseFilters('pageview', filters, params); + + return rawQuery( + ` + select ${field} x, count(*) y + from session as x + where x.session_id in ( + select pageview.session_id + from pageview + ${joinSession} + where pageview.website_id=$1 + and pageview.created_at between $2 and $3 + ${pageviewQuery} + ${sessionQuery} + ) + group by 1 + order by 2 desc + `, + params, + ); +} diff --git a/queries/analytics/session/getSessions.js b/queries/analytics/session/getSessions.js new file mode 100644 index 00000000..ab19ae3d --- /dev/null +++ b/queries/analytics/session/getSessions.js @@ -0,0 +1,19 @@ +import { runQuery } from 'queries'; +import prisma from 'lib/db'; + +export async function getSessions(websites, start_at) { + return runQuery( + prisma.session.findMany({ + where: { + website: { + website_id: { + in: websites, + }, + }, + created_at: { + gte: start_at, + }, + }, + }), + ); +} diff --git a/queries/analytics/stats/getActiveVisitors.js b/queries/analytics/stats/getActiveVisitors.js new file mode 100644 index 00000000..45c972f5 --- /dev/null +++ b/queries/analytics/stats/getActiveVisitors.js @@ -0,0 +1,17 @@ +import { rawQuery } from 'queries'; +import { subMinutes } from 'date-fns'; + +export function getActiveVisitors(website_id) { + const date = subMinutes(new Date(), 5); + const params = [website_id, date]; + + return rawQuery( + ` + select count(distinct session_id) x + from pageview + where website_id=$1 + and created_at >= $2 + `, + params, + ); +} diff --git a/queries/analytics/stats/getRealtimeData.js b/queries/analytics/stats/getRealtimeData.js new file mode 100644 index 00000000..313d757d --- /dev/null +++ b/queries/analytics/stats/getRealtimeData.js @@ -0,0 +1,30 @@ +import { getPageviews } from '../pageview/getPageviews'; +import { getSessions } from '../session/getSessions'; +import { getEvents } from '../event/getEvents'; + +export async function getRealtimeData(websites, time) { + const [pageviews, sessions, events] = await Promise.all([ + getPageviews(websites, time), + getSessions(websites, time), + getEvents(websites, time), + ]); + + return { + pageviews: pageviews.map(({ view_id, ...props }) => ({ + __id: `p${view_id}`, + view_id, + ...props, + })), + sessions: sessions.map(({ session_id, ...props }) => ({ + __id: `s${session_id}`, + session_id, + ...props, + })), + events: events.map(({ event_id, ...props }) => ({ + __id: `e${event_id}`, + event_id, + ...props, + })), + timestamp: Date.now(), + }; +} diff --git a/queries/analytics/stats/getWebsiteStats.js b/queries/analytics/stats/getWebsiteStats.js new file mode 100644 index 00000000..1b22cb37 --- /dev/null +++ b/queries/analytics/stats/getWebsiteStats.js @@ -0,0 +1,29 @@ +import { parseFilters, rawQuery, getDateQuery, getTimestampInterval } from 'queries'; + +export function getWebsiteStats(website_id, start_at, end_at, filters = {}) { + const params = [website_id, start_at, end_at]; + const { pageviewQuery, sessionQuery, joinSession } = parseFilters('pageview', filters, params); + + return rawQuery( + ` + select sum(t.c) as "pageviews", + count(distinct t.session_id) as "uniques", + sum(case when t.c = 1 then 1 else 0 end) as "bounces", + sum(t.time) as "totaltime" + from ( + select pageview.session_id, + ${getDateQuery('pageview.created_at', 'hour')}, + count(*) c, + ${getTimestampInterval('pageview.created_at')} as "time" + from pageview + ${joinSession} + where pageview.website_id=$1 + and pageview.created_at between $2 and $3 + ${pageviewQuery} + ${sessionQuery} + group by 1, 2 + ) t + `, + params, + ); +} diff --git a/queries/index.js b/queries/index.js new file mode 100644 index 00000000..d964854c --- /dev/null +++ b/queries/index.js @@ -0,0 +1,4 @@ +import * as admin from './admin'; +import * as analytics from './analytics'; + +export default { admin, analytics }; diff --git a/yarn.lock b/yarn.lock index fd0a907c..b67d3e7d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1859,6 +1859,14 @@ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.36.tgz#35e11200542cf29068ba787dad57da9bdb82f644" integrity sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ== +JSONStream@1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.4.tgz#615bb2adb0cd34c8f4c447b5f6512fa1d8f16a2e" + integrity sha512-Y7vfi3I5oMOYIr+WxV8NZxDSwcbNgzdKYsTNInmycOq9bUYwGg9ryu57Wg5NLmCjqdFPNUmpMBo3kSJN9tCbXg== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + acorn-dynamic-import@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" @@ -1911,7 +1919,7 @@ ajv-keywords@^5.0.0: dependencies: fast-deep-equal "^3.1.3" -ajv@^6.10.0, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2033,6 +2041,18 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" @@ -2043,6 +2063,11 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + at-least-node@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" @@ -2060,6 +2085,16 @@ autoprefixer@^10.4.4: picocolors "^1.0.0" postcss-value-parser "^4.2.0" +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + axe-core@^4.3.5: version "4.4.2" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.2.tgz#dcf7fb6dea866166c3eab33d68208afe4d5f670c" @@ -2127,6 +2162,13 @@ balanced-match@^2.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9" integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA== +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + bcryptjs@^2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" @@ -2251,6 +2293,11 @@ caniuse-lite@^1.0.30001283, caniuse-lite@^1.0.30001313, caniuse-lite@^1.0.300013 resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001356.tgz" integrity sha512-/30854bktMLhxtjieIxsrJBfs2gTM1pel6MXKF3K+RdIVJZcsn2A2QdhsuR4/p9+R204fZw0zCBBhktX8xWuyQ== +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -2326,6 +2373,20 @@ cli-truncate@2.1.0, cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" +clickhouse@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/clickhouse/-/clickhouse-2.5.0.tgz#29cece9aeb2e4f449ffb75933f32725a8f7798b3" + integrity sha512-3eszr5FUDnApZDCQOnpHVmNk6opTnzDNdZyG8n3MF1kf/dts47e7o2DbKC2xEG22orGMski1Flvf1J6nkUhvZA== + dependencies: + JSONStream "1.3.4" + lodash "4.17.21" + querystring "0.2.0" + request "2.88.0" + stream2asynciter "1.0.3" + through "2.3.8" + tsv "0.2.0" + uuid "3.4.0" + clone-regexp@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f" @@ -2372,6 +2433,13 @@ colorette@^2.0.16: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@2, commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -2417,6 +2485,11 @@ core-js-pure@^3.20.2: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.22.8.tgz#f2157793b58719196ccf9673cc14f3683adc0957" integrity sha512-bOxbZIy9S5n4OVH63XaLVXZ49QKicjowDx/UELyJ68vxfCRpYsbyh/WNZNfEfAk+ekA8vSjt+gCDpvh672bc3w== +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + cors@^2.8.5: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" @@ -2626,6 +2699,13 @@ damerau-levenshtein@^1.0.7: resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + data-uri-to-buffer@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" @@ -2724,6 +2804,11 @@ del@^6.0.0: rimraf "^3.0.2" slash "^3.0.0" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + detect-browser@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca" @@ -2790,6 +2875,14 @@ dotenv@^10.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + electron-to-chromium@^1.4.118, electron-to-chromium@^1.4.84: version "1.4.143" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.143.tgz#10f1bb595ad6cd893c05097039c685dcf5c8e30c" @@ -3166,6 +3259,11 @@ execall@^2.0.0: dependencies: clone-regexp "^2.1.0" +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + extract-react-intl-messages@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/extract-react-intl-messages/-/extract-react-intl-messages-4.1.1.tgz#cd01d99053bb053ecc8410ccdccb9ac56daae91c" @@ -3187,6 +3285,16 @@ extract-react-intl-messages@^4.1.1: sort-keys "^4.0.0" write-json-file "^4.3.0" +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -3293,6 +3401,20 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + formdata-polyfill@^4.0.10: version "4.0.10" resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" @@ -3416,6 +3538,13 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -3502,6 +3631,19 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.0: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + hard-rejection@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" @@ -3572,6 +3714,15 @@ html-tags@^3.2.0: resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg== +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -3846,7 +3997,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typedarray@^1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= @@ -3873,6 +4024,11 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + jest-worker@^26.2.1: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" @@ -3902,6 +4058,11 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -3932,6 +4093,11 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -3944,6 +4110,11 @@ json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -3972,6 +4143,21 @@ jsonify@~0.0.0: resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" integrity sha512-trvBk1ki43VZptdBI5rIlG4YOzyeH/WefQt5rj1grasPn4iiZWKet8nkgc4GlsAylaztn0qZfUYOiTsASJFdNA== +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.0.tgz#e624f259143b9062c92b6413ff92a164c80d3ccb" @@ -4126,7 +4312,7 @@ lodash.truncate@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== -lodash@^4.17.21: +lodash@4.17.21, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4268,6 +4454,18 @@ micromatch@^4.0.4, micromatch@^4.0.5: braces "^3.0.2" picomatch "^2.3.1" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -4472,6 +4670,11 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + object-assign@^4, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -4684,6 +4887,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -5071,11 +5279,31 @@ prop-types@^15.7.2, prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" +psl@^1.1.24: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -5332,6 +5560,32 @@ request-ip@^2.1.3: dependencies: is_js "^0.9.0" +request@2.88.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + require-from-string@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" @@ -5430,7 +5684,7 @@ rxjs@^7.5.1: dependencies: tslib "^2.1.0" -safe-buffer@^5.1.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -5440,6 +5694,11 @@ safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + scheduler@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" @@ -5655,11 +5914,31 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +sshpk@^1.7.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + stable@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stream2asynciter@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream2asynciter/-/stream2asynciter-1.0.3.tgz#7ba9046846c8b1caf36ec30d64a73514f7f44c5a" + integrity sha512-9/dEZW+LQjuW6ub5hmWi4n9Pn8W8qA8k7NAE1isecesA164e73xTdy1CJ3S9o9YS+O21HuiK7T+4uS7FgKDy4w== + string-argv@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" @@ -5942,7 +6221,7 @@ thenby@^1.3.4: resolved "https://registry.yarnpkg.com/thenby/-/thenby-1.3.4.tgz#81581f6e1bb324c6dedeae9bfc28e59b1a2201cc" integrity sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ== -through@^2.3.8: +through@2.3.8, "through@>=2.2.7 <3", through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -5983,6 +6262,14 @@ topojson-client@^3.1.0: dependencies: commander "2" +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + trim-newlines@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" @@ -6020,6 +6307,23 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tsv@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/tsv/-/tsv-0.2.0.tgz#92869a3cb5f50332f3dc90fca82be667db6f72d6" + integrity sha512-GG6xbOP85giXXom0dS6z9uyDsxktznjpa1AuDlPrIXDqDnbhjr9Vk6Us8iz6U1nENL4CPS2jZDvIjEdaZsmc4Q== + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -6154,6 +6458,11 @@ util-deprecate@^1.0.2: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +uuid@3.4.0, uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + uuid@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" @@ -6182,6 +6491,15 @@ vary@^1: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + vue@^3.2.23: version "3.2.36" resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.36.tgz#8daa996e2ced521708de97d066c7c998e8bc3378"