Fix Google Calendar environment variables (#1638)

* passing Google Calendar API info through build process 🈴

* renaming env vars & publishing them to the build process 🐦

* auto checkout not working for Hasura build 🦷

* discovered some not renamed variables 🉐

* adding swap space ☄

* trying to expand Node's heap size 🧐

* underscored rather than dashed 🌾

* trying node 20 🦙

* switching to `python3` 🌮

* updating `node-gyp` & `better-sqlite3` 🛵

* returning error details 🦚

* trying a different mechanism for increasing the Node heap 🦟

* fix: fix logic for checking the host. Now using a whitelist set in config.ts and checking that against the publicURL

* fix: was referencing the cal id with NEXT_PUBLIC_GOOGLE_CAL prefix but it is now GCAL_ - should sort the missing credentials issue

* printing settings for sanity check 🐻

* setting runtime environment 🌲

* trying to set runtime env 👩🏿‍🔧

* grabbing calendar id 🤴🏿

* replacing escapes newlines in private key 🍨

* removing logging 🥾

* fix: body overflow issue when events have long descriptions

* feat: style/design updates to calendar pop overs

* chore: clean up comments

* fix: use ListItem

* fixed issues after review from @dysbulic

* fix: addressed comments from dys' review, removed a cpl of comments and increased the days initially displayed to fill the block

---------

Co-authored-by: luxumbra <me@luxumbra.dev>
This commit is contained in:
δυς
2023-11-15 19:31:55 -05:00
committed by GitHub
parent 04241a3e01
commit 6bbef15904
16 changed files with 751 additions and 429 deletions

View File

@@ -143,8 +143,10 @@ jobs:
USERBACK_TOKEN=${{secrets.USERBACK_TOKEN}}
WEB3_STORAGE_TOKEN=${{secrets.WEB3_STORAGE_TOKEN}}
OPENSEA_API_KEY=${{secrets.OPENSEA_API_KEY}}
GOOGLE_CAL_API_KEY=${{secrets.GOOGLE_CAL_API_KEY}}
GOOGLE_CAL_PRIVATE_KEY=${{secrets.GOOGLE_CAL_PRIVATE_KEY}}
GCAL_PRIVATE_KEY=${{secrets.GCAL_PRIVATE_KEY}}
GCAL_CLIENT_EMAIL=${{secrets.GCAL_CLIENT_EMAIL}}
GCAL_PROJECT_NUMBER=${{secrets.GCAL_PROJECT_NUMBER}}
GCAL_CALENDAR_ID=${{secrets.GCAL_CALENDAR_ID}}
push: true
deploy-frontend:

View File

@@ -32,9 +32,6 @@ env:
HASURA_SECRET: metagame_secret
GA4_ID: G-B1NKK3Q1BP
APP_ENV: development
GOOGLE_CAL_PROJECT_NUMBER: 510169944888
GOOGLE_CAL_CLIENT_EMAIL: metagamecalwebsite@metagamecal.iam.gserviceaccount.com
GOOGLE_CAL_CALENDAR_ID: nih59ktgafmm64ed4qk6ue8vv4
jobs:
start-deployment:
@@ -103,9 +100,6 @@ jobs:
HASURA_TAG: ${{env.HASURA_TAG}}
FRONTEND_TAG: ${{env.FRONTEND_TAG}}
FRONTEND_TARGET: ${{env.FRONTEND_TARGET}}
GOOGLE_CAL_PROJECT_NUMBER: ${{env.GOOGLE_CAL_PROJECT_NUMBER}}
GOOGLE_CAL_CLIENT_EMAIL: ${{env.GOOGLE_CAL_CLIENT_EMAIL}}
GOOGLE_CAL_CALENDAR_ID: ${{env.GOOGLE_CAL_CALENDAR_ID}}
steps:
- name: First Intepolation of Variables
@@ -255,23 +249,18 @@ jobs:
needs: [env, delete-backend, undeploy-backend]
steps:
- name: "Checkout: ${{github.event.pull_request.head.label}}"
uses: actions/checkout@v3
with:
ref: ${{github.event.pull_request.head.sha}}
- name: Set Up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: "Login to Registry: ${{needs.env.outputs.DOCKER_REGISTRY}}"
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ${{needs.env.outputs.DOCKER_REGISTRY}}
username: _json_key
password: ${{secrets.GCP_SA_KEY}}
- name: "Build & Push Container Image: ${{needs.env.outputs.BACKEND_TAG}}"
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
file: docker/backend/Dockerfile
tags: ${{needs.env.outputs.BACKEND_TAG}}
@@ -367,17 +356,17 @@ jobs:
ref: ${{github.event.pull_request.head.sha}}
- name: Set Up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: "Login to Registry: ${{needs.env.outputs.DOCKER_REGISTRY}}"
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ${{needs.env.outputs.DOCKER_REGISTRY}}
username: _json_key
password: ${{secrets.GCP_SA_KEY}}
- name: "Build & Push Container Image: ${{needs.env.outputs.HASURA_TAG}}"
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
file: hasura/Dockerfile
context: hasura
@@ -465,23 +454,18 @@ jobs:
needs: [env, delete-frontend, undeploy-frontend, deploy-hasura, seed-db]
steps:
- name: "Checkout: ${{github.event.pull_request.head.label}}"
uses: actions/checkout@v3
with:
ref: ${{github.event.pull_request.head.sha}}
- name: Set Up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: "Login to Registry: ${{needs.env.outputs.DOCKER_REGISTRY}}"
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ${{needs.env.outputs.DOCKER_REGISTRY}}
username: _json_key
password: ${{secrets.GCP_SA_KEY}}
- name: "Build & Push Container Image: ${{needs.env.outputs.FRONTEND_TAG}}"
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
file: docker/frontend/Dockerfile
tags: ${{needs.env.outputs.FRONTEND_TAG}}
@@ -494,8 +478,10 @@ jobs:
IMGIX_TOKEN=${{secrets.IMGIX_TOKEN}}
WEB3_STORAGE_TOKEN=${{secrets.WEB3_STORAGE_TOKEN}}
OPENSEA_API_KEY=${{secrets.OPENSEA_API_KEY}}
GOOGLE_CAL_API_KEY=${{secrets.GOOGLE_CAL_API_KEY}}
GOOGLE_CAL_PRIVATE_KEY=${{secrets.GOOGLE_CAL_PRIVATE_KEY}}
GCAL_PRIVATE_KEY=${{secrets.GCAL_PRIVATE_KEY}}
GCAL_PROJECT_NUMBER=${{secrets.GCAL_PROJECT_NUMBER}}
GCAL_CLIENT_EMAIL=${{secrets.GCAL_CLIENT_EMAIL}}
GCAL_CALENDAR_ID=${{secrets.GCAL_CALENDAR_ID}}
push: true
deploy-frontend:
@@ -527,7 +513,12 @@ jobs:
--memory ${{needs.env.outputs.FRONTEND_TARGET == 'development' && '5Gi' || '512Mi'}} \
--ingress all \
--max-instances 1 \
--allow-unauthenticated
--allow-unauthenticated \
--set-env-vars GCAL_PRIVATE_KEY="${{secrets.GCAL_PRIVATE_KEY}}" \
--set-env-vars GCAL_PROJECT_NUMBER="${{secrets.GCAL_PROJECT_NUMBER}}" \
--set-env-vars GCAL_CLIENT_EMAIL="${{secrets.GCAL_CLIENT_EMAIL}}" \
--set-env-vars NEXT_PUBLIC_GCAL_CALENDAR_ID="${{secrets.GCAL_CALENDAR_ID}}"
seed-db:
name: Seed Database

View File

@@ -1 +1 @@
16.20.1
20

View File

@@ -1,9 +1,9 @@
FROM node:16-slim as base
FROM node:20-slim as base
WORKDIR /usr/src/app
# Install dependencies not included in the slim image
RUN apt-get update && \
apt-get install -y --no-install-recommends g++ make python git openssl && \
apt-get install -y --no-install-recommends g++ make python3 git openssl && \
apt-get install -y --no-install-recommends --reinstall ca-certificates
# Install dependencies for dev and prod
@@ -44,7 +44,7 @@ RUN yarn backend:build
RUN yarn install --pure-lockfile --production --ignore-scripts --prefer-offline
# Create completely new stage including only necessary files
FROM node:16-slim as app
FROM node:20-slim as app
WORKDIR /app
# Copy necessary files into the stage

View File

@@ -1,9 +1,9 @@
FROM node:16-slim as base
FROM node:20-slim as base
WORKDIR /usr/src/app
# Install dependencies not included in the slim image
RUN apt-get update && \
apt-get install -y --no-install-recommends g++ make python git openssl && \
apt-get install -y --no-install-recommends g++ make python3 git openssl && \
apt-get install -y --no-install-recommends --reinstall ca-certificates
# Install dependencies for dev and prod
@@ -38,7 +38,7 @@ RUN yarn discord-bot build
RUN yarn install --pure-lockfile --production --ignore-scripts --prefer-offline
# Create completely new stage including only necessary files
FROM node:16-slim as app
FROM node:20-slim as app
WORKDIR /app
# Needed at runtime

View File

@@ -7,11 +7,11 @@
# site or dev environment respectively.
ARG TARGET=production
FROM node:16-slim AS base
FROM node:20-slim AS base
WORKDIR /usr/src/app
# Install dependencies not included in the slim image
RUN apt-get update && apt-get install -y --no-install-recommends g++ make python git ca-certificates
RUN apt-get update && apt-get install -y --no-install-recommends g++ make python3 git ca-certificates
# Install dependencies for dev and prod
COPY package.json ./
@@ -51,6 +51,10 @@ ARG USERBACK_TOKEN
ARG CERAMIC_URL https://ceramic.metagame.wtf
ARG WEB3_STORAGE_TOKEN
ARG OPENSEA_API_KEY
ARG GCAL_CALENDAR_ID
ARG GCAL_PRIVATE_KEY
ARG GCAL_CLIENT_EMAIL
ARG GCAL_PROJECT_NUMBER
# ARGs are not available at runtime, so define ENV variables
# These ENVs should match the --set-env-vars in `.github/workflows/gcp-deploy.yaml`
@@ -63,9 +67,13 @@ ENV NEXT_PUBLIC_YOUTUBE_API_KEY $YOUTUBE_API_KEY
ENV NEXT_PUBLIC_HONEYBADGER_API_KEY $HONEYBADGER_API_KEY
ENV NEXT_PUBLIC_USERBACK_TOKEN $USERBACK_TOKEN
ENV NEXT_PUBLIC_CERAMIC_URL $CERAMIC_URL
ENV NEXT_PUBLIC_GCAL_CALENDAR_ID $GCAL_CALENDAR_ID
# These are not exposed to the browser
ENV WEB3_STORAGE_TOKEN $WEB3_STORAGE_TOKEN
ENV OPENSEA_API_KEY $OPENSEA_API_KEY
ENV GCAL_PRIVATE_KEY $GCAL_PRIVATE_KEY
ENV GCAL_CLIENT_EMAIL $GCAL_CLIENT_EMAIL
ENV GCAL_PROJECT_NUMBER $GCAL_PROJECT_NUMBER
ONBUILD RUN yarn web:build
# Delete devDependencies
@@ -77,7 +85,7 @@ ONBUILD RUN yarn web:deps:build
FROM "build-$TARGET" as built
# New stage including only necessary files
FROM node:16-slim AS app
FROM node:20-slim AS app
WORKDIR /app
# Copy necessary files into the stage

View File

@@ -13,7 +13,7 @@
"docker:build": "docker-compose up --build -d",
"docker:stop": "docker-compose down",
"docker:clean": "docker-compose down -v",
"docker:dev": "COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose up --build",
"docker:dev": "DOCKER_BUILDKIT=1 docker compose up --build",
"build": "lerna run --concurrency 1 --stream build",
"web:dev": "lerna run dev --parallel --scope @metafam/web --include-dependencies",
"web:build": "lerna run build --scope @metafam/web --include-dependencies --stream",
@@ -102,7 +102,9 @@
"ethers": "5.7.0",
"graphql": "16.8.0",
"multihashes": "4.0.3",
"@urql/core": "3.2.2"
"@urql/core": "3.2.2",
"node-gyp": "10.0.1",
"better-sqlite3": "9.0.0"
},
"browserslist": [
"defaults",

View File

@@ -44,6 +44,7 @@ export type MetaColors = ChakraTheme['colors'] & {
landing600: string;
landing650: string;
landingDarkGlass: string;
darkPurpleAlpha: ColorHues;
midnightBlue: string;
royalBlue: string;
deepMagenta: string;
@@ -184,4 +185,16 @@ export const colors: MetaColors = {
landing600: '#DF9BFF',
landing650: '#DFB9D7',
landingDarkGlass: 'rgba(27, 13, 42, 0.9)',
darkPurpleAlpha: {
50: 'rgba(27, 13, 42, 0.05)',
100: 'rgba(27, 13, 42, 0.1)',
200: 'rgba(27, 13, 42, 0.2)',
300: 'rgba(27, 13, 42, 0.3)',
400: 'rgba(27, 13, 42, 0.4)',
500: 'rgba(27, 13, 42, 0.5)',
600: 'rgba(27, 13, 42, 0.6)',
700: 'rgba(27, 13, 42, 0.7)',
800: 'rgba(27, 13, 42, 0.8)',
900: 'rgba(27, 13, 42, 0.98)',
},
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

@@ -8,8 +8,9 @@ import {
ExternalLinkIcon,
Flex,
HStack,
IconButton,
Image,
List,
ListItem,
LoadingState,
MetaButton,
Popover,
@@ -26,16 +27,11 @@ import {
VStack,
} from '@metafam/ds';
import { MetaLink } from 'components/Link';
import { MarkdownViewer } from 'components/MarkdownViewer';
import type { GoogleCalEventType } from 'lib/hooks/useCalendar';
import type { GroupedEventsType } from 'lib/hooks/useCalendar';
import { useCalendar } from 'lib/hooks/useCalendar';
import { DateTime } from 'luxon';
import React, { useEffect, useRef, useState } from 'react';
type GroupedEventsType = {
date: string;
events: GoogleCalEventType[];
};
import { safelyParseContent } from 'utils/stringHelpers';
const loadMoreButtonStyles: ButtonProps = {
display: 'flex',
@@ -53,14 +49,13 @@ const loadMoreButtonStyles: ButtonProps = {
export const Calendar: React.FC = () => {
const [calendar, setCalendar] = useState<GroupedEventsType[]>([]);
const [loadingMore, setLoadingMore] = useState(false);
const showHowMany = 3;
const showHowMany = 4;
const {
fetching,
error,
ics,
eventsGroupedByDay,
totalEvents,
cleanDescription,
buildAddToCalendarLink,
limit,
setLimit,
@@ -237,8 +232,8 @@ export const Calendar: React.FC = () => {
})
.toUpperCase()}
</Box>
<VStack
as="ol"
<List
as={VStack}
className="calendar__day--events"
ml={0}
width="100%"
@@ -247,101 +242,72 @@ export const Calendar: React.FC = () => {
}}
>
{day &&
day.events?.map((event) => (
<Box
as="li"
position="relative"
className="calendar__day--event"
width="100%"
px={5}
py={2}
backgroundColor="blackAlpha.500"
borderRadius="md"
overflow="hidden"
role="group"
_groupHover={{
backgroundColor: 'blackAlpha.600',
}}
>
<Popover colorScheme="purple">
<Event
title={event.summary}
start={
'dateTime' in event.start
? DateTime.fromISO(
event.start.dateTime,
).toLocaleString(
DateTime.TIME_24_SIMPLE,
)
: DateTime.fromISO(
event.start.date,
).toLocaleString(
DateTime.TIME_24_SIMPLE,
)
}
end={
'dateTime' in event.end
? DateTime.fromISO(
event.end.dateTime,
).toLocaleString(
DateTime.TIME_24_SIMPLE,
)
: DateTime.fromISO(
event.end.date,
).toLocaleString(
DateTime.TIME_24_SIMPLE,
)
}
/>
day.events?.map((event) => {
const { cover, description } = event;
<EventPopover
title={event.summary}
start={
'dateTime' in event.start
? DateTime.fromISO(
event.start.dateTime,
).toLocaleString(
DateTime.TIME_24_SIMPLE,
)
: DateTime.fromISO(
event.start.date,
).toLocaleString(
DateTime.TIME_24_SIMPLE,
)
}
end={
'dateTime' in event.end
? DateTime.fromISO(
event.end.dateTime,
).toLocaleString(
DateTime.TIME_24_SIMPLE,
)
: DateTime.fromISO(
event.end.date,
).toLocaleString(
DateTime.TIME_24_SIMPLE,
)
}
description={cleanDescription(
event.description,
)}
htmlLink={event.htmlLink}
location={event.location}
addToCalUrl={buildAddToCalendarLink(event)}
/>
</Popover>
<Box
position="absolute"
inset={0}
return (
<ListItem
key={event.id}
position="relative"
className="calendar__day--event"
width="100%"
px={5}
py={2}
backgroundColor="blackAlpha.500"
borderRadius="md"
overflow="hidden"
role="group"
_groupHover={{
backgroundColor: 'blackAlpha.600',
}}
transition="all 0.1s ease-in-out"
zIndex={-1}
/>
</Box>
))}
</VStack>
>
<Popover colorScheme="purple">
<Event
title={event.summary}
start={DateTime.fromISO(
'dateTime' in event.start
? event.start.dateTime
: event.start.date,
).toLocaleString(DateTime.TIME_24_SIMPLE)}
end={DateTime.fromISO(
'dateTime' in event.end
? event.end.dateTime
: event.end.date,
).toLocaleString(DateTime.TIME_24_SIMPLE)}
/>
<EventPopover
title={event.summary}
start={DateTime.fromISO(
'dateTime' in event.start
? event.start.dateTime
: event.start.date,
).toLocaleString(DateTime.TIME_24_SIMPLE)}
end={DateTime.fromISO(
'dateTime' in event.end
? event.end.dateTime
: event.end.date,
).toLocaleString(DateTime.TIME_24_SIMPLE)}
description={description}
cover={cover}
htmlLink={event.htmlLink}
location={event.location}
addToCalUrl={buildAddToCalendarLink(event)}
/>
</Popover>
<Box
position="absolute"
inset={0}
_groupHover={{
backgroundColor: 'blackAlpha.600',
}}
transition="all 0.1s ease-in-out"
zIndex={-1}
/>
</ListItem>
);
})}
</List>
</Box>
);
})}
@@ -379,6 +345,7 @@ interface EventPopoverType {
start: string;
end: string;
description: string;
cover?: string;
htmlLink: string;
location: string;
addToCalUrl: string;
@@ -389,13 +356,14 @@ const EventPopover = ({
start,
end,
description,
cover,
htmlLink,
location,
addToCalUrl,
}: EventPopoverType) => (
<Portal>
<PopoverContent
backgroundColor="purpleTag70"
bgColor="darkPurpleAlpha.200"
backdropFilter="blur(10px)"
boxShadow="0 0 10px rgba(0,0,0,0.3)"
borderWidth={0}
@@ -406,85 +374,118 @@ const EventPopover = ({
},
}}
>
<Box
bg="transparent"
borderWidth={0}
position="absolute"
left={-1}
top={0}
width="100%"
textAlign="center"
>
<Image
src="/assets/logo.png"
minH="15px"
minW="12px"
maxH="15px"
mx="auto"
transform="translateY(-7px)"
<Box role="group" position="relative" w="full" h="full">
<PopoverCloseButton
zIndex={3}
top={'calc(var(--chakra-space-2) + 1px)'}
/>
</Box>
<PopoverCloseButton />
<PopoverHeader
borderColor="cyanText"
borderBottomWidth={1}
fontWeight="600"
fontFamily="exo"
>
{title}
</PopoverHeader>
<PopoverBody>
<PopoverHeader
position={'relative'}
borderColor="whiteAlpha.300"
borderBottomWidth={1}
fontWeight="600"
fontFamily="exo"
zIndex={2}
>
{title}
</PopoverHeader>
<PopoverBody position="relative" zIndex={2}>
<Box
as="dl"
maxH={'200px'}
overflowY="auto"
pr={2}
sx={{
dt: {
fontSize: 'sm',
fontWeight: '600',
},
}}
>
<Box as="dt">Time</Box>
<Box as="dd" fontWeight="400" fontFamily="body" fontSize="xs">
{`${start} ${end}`}
</Box>
{description && (
<Box>
<Box as="dt">Description</Box>
<Box as="dd" fontWeight="400" fontFamily="body" fontSize="xs">
{safelyParseContent(description)}
</Box>
</Box>
)}
{location && (
<Box>
<Box as="dt">Location</Box>
<Box as="dd" fontWeight="400" fontFamily="body" fontSize="xs">
{location}
</Box>
</Box>
)}
</Box>
</PopoverBody>
<PopoverFooter position="relative" borderTopWidth={0} zIndex={2}>
<ButtonGroup
variant="ghost"
colorScheme="cyan"
justifyContent="space-between"
w="full"
>
<Button
as={MetaLink}
aria-label="Add to your calendar"
fontSize="sm"
href={addToCalUrl}
leftIcon={<CalendarAddIcon />}
isExternal
>
Add to my calendar
</Button>
<Button
aria-label="View calendar"
as={MetaLink}
fontSize="sm"
href={htmlLink}
isExternal
leftIcon={<ExternalLinkIcon />}
>
View full event
</Button>
</ButtonGroup>
</PopoverFooter>
<Box
as="dl"
position="absolute"
borderRadius="md"
overflow={'hidden'}
inset={0}
zIndex={0}
sx={{
dt: {
fontSize: 'sm',
fontWeight: '600',
'&::after': {
position: 'absolute',
content: '""',
boxShadow:
'0 0 80px 10px var(--chakra-colors-darkPurpleAlpha-900) inset',
w: 'full',
h: 'full',
inset: 0,
opacity: cover ? 0.8 : 0.7,
zIndex: 1,
},
}}
>
<Box as="dt">Date &amp; Time</Box>
<Box as="dd" fontWeight="400" fontFamily="body" fontSize="xs">
{`${start} ${end}`}
</Box>
{description && (
<Box>
<Box as="dt">Description</Box>
<Box as="dd" fontWeight="400" fontFamily="body" fontSize="xs">
<MarkdownViewer>{description}</MarkdownViewer>
</Box>
</Box>
)}
{location && (
<Box>
<Box as="dt">Location</Box>
<Box as="dd" fontWeight="400" fontFamily="body" fontSize="xs">
{location}
</Box>
</Box>
{cover && (
<Image
src={cover}
alt={title}
objectFit="cover"
h="full"
w="auto"
opacity={0.2}
zIndex={0}
/>
)}
</Box>
</PopoverBody>
<PopoverFooter borderTopWidth={0}>
<ButtonGroup variant="ghost" colorScheme="cyan">
<IconButton
as={MetaLink}
aria-label="Add to your calendar"
fontSize="lg"
href={addToCalUrl}
icon={<CalendarAddIcon />}
isExternal
/>
<IconButton
aria-label="View calendar"
as={MetaLink}
fontSize="lg"
href={htmlLink}
isExternal
icon={<ExternalLinkIcon />}
/>
</ButtonGroup>
</PopoverFooter>
</Box>
</PopoverContent>
</Portal>
);

View File

@@ -23,11 +23,21 @@ export const CONFIG = {
'https://ceramic-clay.3boxlabs.com', // testnet
ceramicNetwork:
process.env.NEXT_PUBLIC_CERAMIC_NETWORK || 'mainnet' || 'testnet-clay',
calendarId: process.env.NEXT_PUBLIC_GOOGLE_CAL_CALENDAR_ID,
googleDataAPIKey: process.env.NEXT_PUBLIC_YOUTUBE_API_KEY,
web3StorageToken: process.env.WEB3_STORAGE_TOKEN,
openseaAPIKey: process.env.OPENSEA_API_KEY,
alchemyAPIKey: process.env.NEXT_PUBLIC_ALCHEMY_API_KEY,
mainnetRPC: process.env.NEXT_PUBLIC_MAINNET_RPC || 'https://eth.llamarpc.com',
metagameCalendarBackend: `${process.env.NEXT_PUBLIC_FRONTEND_URL}/api/events`,
calendarEndpoint: '/api/events',
gcal: {
calendarId: process.env.NEXT_PUBLIC_GCAL_CALENDAR_ID,
privateKey: process.env.GCAL_PRIVATE_KEY?.replace(/\\n/g, '\n'),
clientEmail: process.env.GCAL_CLIENT_EMAIL,
projectNumber: process.env.GCAL_PROJECT_NUMBER,
scopes: ['https://www.googleapis.com/auth/calendar'],
whitelist: [
'https://*.metagame.wtf',
'https://frontend-pr-*-mjhnbmqqna-uk.a.run.app',
],
},
};

View File

@@ -3,26 +3,27 @@ import { CONFIG } from 'config';
import { DateTime } from 'luxon';
import { useCallback, useEffect, useState } from 'react';
type GoogleCalEventDateTimeType =
export type GoogleCalEventDateTimeType =
| {
date: string;
}
| {
dateTime: string;
timeZone: string;
}
| {
date: string;
};
export type GoogleCalEventType = {
id: string;
summary: string;
description: string;
cover?: string;
start: GoogleCalEventDateTimeType;
end: GoogleCalEventDateTimeType;
htmlLink: string;
location: string;
};
type UseCalendarReturnTypes = {
export type UseCalendarReturnTypes = {
events: Maybe<GoogleCalEventType[]>;
timeZone: TimeZonesType;
fetching: boolean;
@@ -32,7 +33,6 @@ type UseCalendarReturnTypes = {
totalEvents: number;
limit: number;
setLimit: (limit: number) => void;
cleanDescription: (desc: string) => string;
buildAddToCalendarLink: (event: GoogleCalEventType) => string;
};
@@ -41,12 +41,12 @@ type TimeZonesType = {
calendar: string;
};
type GroupedEventsType = {
export type GroupedEventsType = {
date: string;
events: GoogleCalEventType[];
};
type CalendarDataType = {
export type CalendarDataType = {
events: Maybe<GoogleCalEventType[]>;
days: GroupedEventsType[];
timeZone: TimeZonesType;
@@ -59,7 +59,10 @@ type CalendarDataType = {
* @returns calendar data (events, timezone, fetching, error, ics, eventsGroupedByDay, totalEvents, limit, setLimit)
*/
export const useCalendar = (clamp?: number): UseCalendarReturnTypes => {
const { metagameCalendarBackend, calendarId } = CONFIG;
const {
calendarEndpoint,
gcal: { calendarId },
} = CONFIG;
const [calendarData, setCalendarData] = useState<CalendarDataType>({
events: null,
days: [],
@@ -71,32 +74,82 @@ export const useCalendar = (clamp?: number): UseCalendarReturnTypes => {
});
const [limit, setLimit] = useState<number>(clamp || 0);
const [fetching, setFetching] = useState(false);
const [error, setError] = useState<Error | undefined>(undefined);
const [error, setError] = useState<Error>();
const calendarICS = `https://calendar.google.com/calendar/ical/${calendarId}%40group.calendar.google.com/public/basic.ics`;
// strip out the +++cover+++ from the description
const cleanDescription = (desc: string) =>
desc ? desc.replace(/(\+\+\+).*(\+\+\+)/, '') : '';
/**
* sanitize the description & get the cover image url if there is one and return the url & sanitized description
*/
const cleanDescription = (
desc: string,
): { cover?: string; description: string; originalDesc?: string } => {
if (!desc) {
return {
cover: undefined,
description: '',
originalDesc: desc,
};
}
function extractCoverUrl(input: string) {
const splitInput = input.split('+++<br>');
const coverSection = splitInput.length > 1 ? splitInput[1] : null;
const urlRegex = /(https?:\/\/[^"\s<]+)/g;
let coverUrl;
const modifiedInput = splitInput[0];
if (coverSection) {
const urls = coverSection.match(urlRegex);
if (urls && urls.length) {
coverUrl = urls.at(-1);
}
}
return {
coverUrl,
modifiedInput,
};
}
const { coverUrl, modifiedInput } = extractCoverUrl(desc);
const cleanRegex =
/(^(?:<br>)+|(?:<br>)+$|(?:<br>){2,})|(?:<\w+><\/\w+>\s*)+/g;
const cleanedDesc = modifiedInput.replace(cleanRegex, '');
return {
cover: coverUrl,
description: cleanedDesc,
originalDesc: desc,
};
};
/**
* Builds a google calendar event url for adding to your calendar
* Builds a google calendar event url for adding to users calendar
* */
const buildAddToCalendarLink = (event: GoogleCalEventType) => {
const start =
'dateTime' in event.start
? DateTime.fromISO(event.start.dateTime)
: DateTime.fromISO(event.start.date);
const end =
'dateTime' in event.end
? DateTime.fromISO(event.end.dateTime)
: DateTime.fromISO(event.end.date);
const start = DateTime.fromISO(
'dateTime' in event.start ? event.start.dateTime : event.start.date,
);
const end = DateTime.fromISO(
'dateTime' in event.end ? event.end.dateTime : event.end.date,
);
const title = event.summary;
const { location } = event;
const details = `${cleanDescription(event.description)}`;
const details = `${
cleanDescription(event.description).description
} \n\n<a href="${event.htmlLink}">MetaGame calendar event link</a>`;
const dates = `${start.toFormat('yyyyMMdd')}T${start.toFormat(
'HHmmss',
)}/${end.toFormat('yyyyMMdd')}T${end.toFormat('HHmmss')}`;
const href = `https://www.google.com/calendar/render?action=TEMPLATE&text=${title}&dates=${dates}&details=${details}&location=${location}&sf=true&output=xml`;
const href =
'https://www.google.com/calendar/render' +
`?action=TEMPLATE&text=${title}&dates=${dates}` +
`&details=${encodeURIComponent(details)}&location=${location}` +
'&sf=true&output=xml';
return href;
};
@@ -105,22 +158,60 @@ export const useCalendar = (clamp?: number): UseCalendarReturnTypes => {
if (calendarData.days.length > 0) return;
setFetching(true);
const res = await fetch(metagameCalendarBackend);
const res = await fetch(calendarEndpoint);
const data = await res.json();
const { days, events: fetchedEvents } = data;
const { days, events: fetchedEvents, error: errorMsg } = data;
if (res.status !== 200 || !data) {
throw new Error('Error fetching data');
throw new Error(errorMsg || 'Error fetching calendar data.');
}
const usersTimeZone =
DateTime.local().offsetNameShort || fetchedEvents.timeZone;
// Sanitize the events descriptions & get the cover image url if there is one
const sanitizedEvents = fetchedEvents.items.map(
(event: GoogleCalEventType) => {
const { description } = event;
const { cover, description: cleanedDesc } =
cleanDescription(description);
return {
...event,
description: cleanedDesc,
cover,
};
},
);
// Sanitize the grouped events descriptions & get the cover image url if there is one
const sanitizedDays = days.map((day: GroupedEventsType) => {
const { events } = day;
const cleanedEvents = events.map((event: GoogleCalEventType) => {
const { description } = event;
const { cover, description: cleanedDesc } =
cleanDescription(description);
return {
...event,
description: cleanedDesc,
cover,
};
});
return {
...day,
events: cleanedEvents,
};
});
const calValues: CalendarDataType = {
events: fetchedEvents.items,
days,
timeZone: { users: usersTimeZone, calendar: fetchedEvents.timeZone },
totalEvents: fetchedEvents.items.length,
days: sanitizedDays,
timeZone: {
users: usersTimeZone,
calendar: fetchedEvents.timeZone,
},
totalEvents: sanitizedEvents.length,
};
setCalendarData(calValues);
setError(undefined);
@@ -130,7 +221,7 @@ export const useCalendar = (clamp?: number): UseCalendarReturnTypes => {
} finally {
setFetching(false);
}
}, [metagameCalendarBackend, calendarData]);
}, [calendarData, calendarEndpoint]);
useEffect(() => {
if (calendarData.days.length > 0) {
@@ -139,10 +230,10 @@ export const useCalendar = (clamp?: number): UseCalendarReturnTypes => {
}
fetchCalendarData();
}, [metagameCalendarBackend, calendarData, fetchCalendarData]);
}, [calendarData, fetchCalendarData]);
if (error) {
console.error('useCalendar error', error);
console.error({ 'useCalendar error': error });
}
return {
@@ -153,7 +244,6 @@ export const useCalendar = (clamp?: number): UseCalendarReturnTypes => {
ics: calendarICS,
eventsGroupedByDay: calendarData.days,
totalEvents: calendarData.totalEvents,
cleanDescription,
buildAddToCalendarLink,
limit,
setLimit,

View File

@@ -5,7 +5,7 @@
"type": "module",
"scripts": {
"dev": "concurrently \"next\" \"yarn generate --watch\"",
"build": "yarn generate:graphql && next build",
"build": "yarn generate:graphql && NODE_OPTIONS='--max-old-space-size=5120' next build",
"start": "next start",
"typecheck": "tsc --noEmit --pretty",
"generate": "yarn generate:graphql",

View File

@@ -3,14 +3,6 @@ import { calendar_v3, google } from 'googleapis';
import { DateTime } from 'luxon';
import { NextApiRequest, NextApiResponse } from 'next';
const options = {
PRIVATE_KEY: process.env.GOOGLE_CAL_PRIVATE_KEY,
CLIENT_EMAIL: process.env.NEXT_PUBLIC_GOOGLE_CAL_CLIENT_EMAIL,
PROJECT_NUMBER: process.env.NEXT_PUBLIC_GOOGLE_CAL_PROJECT_NUMBER,
CALENDAR_ID: process.env.NEXT_PUBLIC_GOOGLE_CAL_CALENDAR_ID,
SCOPES: ['https://www.googleapis.com/auth/calendar'],
};
type GoogleCalEventDateTimeType =
| {
dateTime: string;
@@ -31,92 +23,100 @@ export type GoogleCalEventType = {
export const cleanDescription = (desc: string): string =>
desc ? desc.replace(/(\+\+\+).*(\+\+\+)/, '') : desc;
export const matchHostToPattern = (host: string, pattern: string): boolean => {
const regexPattern = pattern
.replace(/[.+?^${}()|[\]\\]/g, '\\$&')
.replace(/\*/g, '.*');
const regex = new RegExp(`^${regexPattern}$`);
return regex.test(host);
};
export const isHostWhitelisted = (host: string, whitelist: string[]): boolean =>
whitelist.some((pattern) => matchHostToPattern(host, pattern));
export default async (
req: NextApiRequest,
res: NextApiResponse,
): Promise<void> => {
const { host } = req.headers;
const { publicURL } = CONFIG;
const publicHost = publicURL?.replace('https://', '').replace('http://', '');
if (req.method === 'GET') {
const calId = options.CALENDAR_ID || '';
const calendarId = `${calId}@group.calendar.google.com`;
const { publicURL, gcal } = CONFIG;
const calendarId = `${gcal.calendarId}@group.calendar.google.com`;
// strip out the +++cover+++ from the description
const canWhitelist = !!publicURL && gcal.whitelist.length > 0;
const isWhitelisted = canWhitelist
? isHostWhitelisted(publicURL, gcal.whitelist)
: true;
const groupEventsByDay = (items: GoogleCalEventType[]) => {
const groupedEvents = items.reduce((acc, event) => {
// console.log('event', {acc, event});
if (req.method !== 'GET') {
res.status(405).json({ error: 'Only GET requests allowed.' });
return;
}
if (!isWhitelisted) {
res.status(403).json({
error: `Traffic not allowed from ${publicURL}.`,
});
return;
}
if (!gcal.privateKey || !gcal.clientEmail) {
res.status(500).json({ error: 'Missing Calendar Credentials' });
return;
}
if (!gcal.calendarId) {
res.status(500).json({ error: 'Missing Calendar ID' });
return;
}
const start =
'dateTime' in event.start
? DateTime.fromISO(event.start.dateTime, {
zone: event.start.timeZone,
}).toLocal()
: DateTime.fromISO(event.start.date).toLocal();
const groupEventsByDay = (items: GoogleCalEventType[]) => {
const groupedEvents = items.reduce((acc, event) => {
const start =
'dateTime' in event.start
? DateTime.fromISO(event.start.dateTime, {
zone: event.start.timeZone,
}).toLocal()
: DateTime.fromISO(event.start.date).toLocal();
const dateKey = start.toFormat('yyyy-MM-dd');
if (!acc[dateKey]) {
acc[dateKey] = [];
}
acc[dateKey].push(event);
return acc;
}, {} as Record<string, GoogleCalEventType[]>);
const dateKey = start.toFormat('yyyy-MM-dd');
acc[dateKey] ??= [];
const days = Object.entries(groupedEvents).map(([date, calEvents]) => ({
date,
events: calEvents as GoogleCalEventType[],
}));
acc[dateKey].push(event);
return acc;
}, {} as Record<string, GoogleCalEventType[]>);
return days;
const days = Object.entries(groupedEvents).map(([date, calEvents]) => ({
date,
events: calEvents as GoogleCalEventType[],
}));
return days;
};
const auth = new google.auth.JWT(
gcal.clientEmail,
undefined,
gcal.privateKey,
['https://www.googleapis.com/auth/calendar.readonly'],
);
const calendar = google.calendar({ version: 'v3', auth });
try {
const params: calendar_v3.Params$Resource$Events$List = {
calendarId,
timeMin: new Date().toISOString(),
timeMax: DateTime.now().plus({ days: 30 }).toISO() || '',
singleEvents: true,
orderBy: 'startTime',
};
const result = await calendar.events.list(params);
const events = result.data;
const days = groupEventsByDay(events.items as GoogleCalEventType[]);
if (req.method !== 'GET') {
res.status(405).end(); // Method Not Allowed
return;
}
if (host !== publicHost) {
res.status(403).end(); // Forbidden
return;
}
if (!options.PRIVATE_KEY || !options.CLIENT_EMAIL) {
res.status(500).json({ error: 'Missing Google Cal Credentials' });
return;
}
if (!calendarId) {
res.status(500).json({ error: 'Missing Google Cal Calendar ID' });
return;
}
const calData = { events, days };
const auth = new google.auth.JWT(
options.CLIENT_EMAIL,
undefined,
options.PRIVATE_KEY,
['https://www.googleapis.com/auth/calendar.readonly'],
);
const calendar = google.calendar({ version: 'v3', auth });
try {
const params: calendar_v3.Params$Resource$Events$List = {
calendarId,
timeMin: DateTime.now().toISO() || '',
timeMax: DateTime.now().plus({ days: 30 }).toISO() || '',
singleEvents: true,
orderBy: 'startTime',
};
const result = await calendar.events.list(params);
const events = result.data;
const days = groupEventsByDay(events.items as GoogleCalEventType[]);
const calData = { events, days };
res.status(200).json(calData);
} catch (err) {
console.error('err', err);
res.status(500).json({ error: `${err}` });
}
} else {
res.status(405).end(); // Method Not Allowed
res.status(200).json(calData);
} catch (err) {
console.error({ err });
res.status(500).json({ error: (err as Error).message });
}
};

391
yarn.lock
View File

@@ -3622,6 +3622,18 @@
dependencies:
multiformats "^9.5.4"
"@isaacs/cliui@^8.0.2":
version "8.0.2"
resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
dependencies:
string-width "^5.1.2"
string-width-cjs "npm:string-width@^4.2.0"
strip-ansi "^7.0.1"
strip-ansi-cjs "npm:strip-ansi@^6.0.1"
wrap-ansi "^8.1.0"
wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
"@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@@ -4755,6 +4767,17 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
"@npmcli/agent@^2.0.0":
version "2.2.0"
resolved "https://registry.yarnpkg.com/@npmcli/agent/-/agent-2.2.0.tgz#e81f00fdb2a670750ff7731bbefb47ecbf0ccf44"
integrity sha512-2yThA1Es98orMkpSLVqlDZAMPK3jHJhifP2gnNUdk1754uZ8yI5c+ulCoVG+WlntQA6MzhrURMXjSd9Z7dJ2/Q==
dependencies:
agent-base "^7.1.0"
http-proxy-agent "^7.0.0"
https-proxy-agent "^7.0.1"
lru-cache "^10.0.1"
socks-proxy-agent "^8.0.1"
"@npmcli/ci-detect@^1.0.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@npmcli/ci-detect/-/ci-detect-1.4.0.tgz#18478bbaa900c37bfbd8a2006a6262c62e8b0fe1"
@@ -4766,6 +4789,13 @@
"@gar/promisify" "^1.0.1"
semver "^7.3.5"
"@npmcli/fs@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.0.tgz#233d43a25a91d68c3a863ba0da6a3f00924a173e"
integrity sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==
dependencies:
semver "^7.3.5"
"@npmcli/git@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-2.1.0.tgz#2fbd77e147530247d37f325930d457b3ebe894f6"
@@ -5069,6 +5099,11 @@
version "1.0.1"
resolved "https://registry.yarnpkg.com/@pedrouid/environment/-/environment-1.0.1.tgz#858f0f8a057340e0b250398b75ead77d6f4342ec"
"@pkgjs/parseargs@^0.11.0":
version "0.11.0"
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
"@popperjs/core@^2.9.3":
version "2.11.8"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
@@ -6565,6 +6600,11 @@ abbrev@1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
abbrev@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf"
integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==
abort-controller@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
@@ -6742,9 +6782,10 @@ ansi-styles@^5.0.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
ansi-styles@^6.0.0:
ansi-styles@^6.0.0, ansi-styles@^6.1.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
ansicolors@~0.3.2:
version "0.3.2"
@@ -7301,12 +7342,13 @@ before-after-hook@^2.2.0:
version "2.2.3"
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c"
better-sqlite3@^7.0.0:
version "7.6.2"
resolved "https://registry.yarnpkg.com/better-sqlite3/-/better-sqlite3-7.6.2.tgz#47cd8cad5b9573cace535f950ac321166bc31384"
better-sqlite3@9.0.0, better-sqlite3@^7.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/better-sqlite3/-/better-sqlite3-9.0.0.tgz#bca6026fa1e9e5af62bfef448a7d8402d4549958"
integrity sha512-lDxQ9qg/XuUHZG6xzrQaMHkNWl37t35/LPB/VJGV8DdScSuGFNfFSqgscXEd8UIuyk/d9wU8iaMxQa4If5Wqog==
dependencies:
bindings "^1.5.0"
prebuild-install "^7.1.0"
prebuild-install "^7.1.1"
big-integer@^1.6.48:
version "1.6.51"
@@ -7683,6 +7725,24 @@ cacache@^15.0.5, cacache@^15.2.0:
tar "^6.0.2"
unique-filename "^1.1.1"
cacache@^18.0.0:
version "18.0.0"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.0.tgz#17a9ecd6e1be2564ebe6cdca5f7cfed2bfeb6ddc"
integrity sha512-I7mVOPl3PUCeRub1U8YoGz2Lqv9WOBpobZ8RyWFXmReuILz+3OAyTa5oH3QPdtKZD7N0Yk00aLfzn0qvp8dZ1w==
dependencies:
"@npmcli/fs" "^3.1.0"
fs-minipass "^3.0.0"
glob "^10.2.2"
lru-cache "^10.0.1"
minipass "^7.0.3"
minipass-collect "^1.0.2"
minipass-flush "^1.0.5"
minipass-pipeline "^1.2.4"
p-map "^4.0.0"
ssri "^10.0.0"
tar "^6.1.11"
unique-filename "^3.0.0"
cacheable-lookup@^5.0.3:
version "5.0.4"
resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005"
@@ -10599,6 +10659,11 @@ expect@^29.0.0, expect@^29.6.3:
jest-message-util "^29.6.3"
jest-util "^29.6.3"
exponential-backoff@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6"
integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==
express-graphql@0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/express-graphql/-/express-graphql-0.12.0.tgz#58deabc309909ca2c9fe2f83f5fbe94429aa23df"
@@ -11024,6 +11089,14 @@ for-each@^0.3.3:
dependencies:
is-callable "^1.1.3"
foreground-child@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d"
integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==
dependencies:
cross-spawn "^7.0.0"
signal-exit "^4.0.1"
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
@@ -11141,6 +11214,13 @@ fs-minipass@^2.0.0, fs-minipass@^2.1.0:
dependencies:
minipass "^3.0.0"
fs-minipass@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54"
integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==
dependencies:
minipass "^7.0.3"
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -11350,6 +11430,17 @@ glob@7.1.7:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^10.2.2, glob@^10.3.10:
version "10.3.10"
resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b"
integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==
dependencies:
foreground-child "^3.1.0"
jackspeak "^2.3.5"
minimatch "^9.0.1"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
path-scurry "^1.10.1"
glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
@@ -11477,9 +11568,10 @@ got@^11.8.5:
p-cancelable "^2.0.0"
responselike "^2.0.0"
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.9:
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
graphemer@^1.4.0:
version "1.4.0"
@@ -11839,9 +11931,10 @@ htmlparser2@^8.0:
domutils "^3.0.1"
entities "^4.4.0"
http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0:
http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
http-errors@1.8.0:
version "1.8.0"
@@ -11950,6 +12043,14 @@ https-proxy-agent@^7.0.0:
agent-base "^7.0.2"
debug "4"
https-proxy-agent@^7.0.1:
version "7.0.2"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b"
integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==
dependencies:
agent-base "^7.0.2"
debug "4"
human-signals@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
@@ -12733,6 +12834,11 @@ isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
isexe@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d"
integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==
iso-random-stream@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/iso-random-stream/-/iso-random-stream-2.0.2.tgz#a24f77c34cfdad9d398707d522a6a0cc640ff27d"
@@ -12920,6 +13026,15 @@ iterator.prototype@^1.1.0:
has-tostringtag "^1.0.0"
reflect.getprototypeof "^1.0.3"
jackspeak@^2.3.5:
version "2.3.6"
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8"
integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==
dependencies:
"@isaacs/cliui" "^8.0.2"
optionalDependencies:
"@pkgjs/parseargs" "^0.11.0"
jake@^10.8.5:
version "10.8.7"
resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.7.tgz#63a32821177940c33f356e0ba44ff9d34e1c7d8f"
@@ -14221,6 +14336,11 @@ lowercase-keys@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2"
lru-cache@^10.0.1, "lru-cache@^9.1.1 || ^10.0.0":
version "10.0.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.1.tgz#0a3be479df549cca0e5d693ac402ff19537a6b7a"
integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==
lru-cache@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
@@ -14275,6 +14395,23 @@ make-error@1.x, make-error@^1.1.1:
version "1.3.6"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
make-fetch-happen@^13.0.0:
version "13.0.0"
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz#705d6f6cbd7faecb8eac2432f551e49475bfedf0"
integrity sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==
dependencies:
"@npmcli/agent" "^2.0.0"
cacache "^18.0.0"
http-cache-semantics "^4.1.1"
is-lambda "^1.0.1"
minipass "^7.0.2"
minipass-fetch "^3.0.0"
minipass-flush "^1.0.5"
minipass-pipeline "^1.2.4"
negotiator "^0.6.3"
promise-retry "^2.0.1"
ssri "^10.0.0"
make-fetch-happen@^8.0.9:
version "8.0.14"
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz#aaba73ae0ab5586ad8eaa68bd83332669393e222"
@@ -14952,6 +15089,13 @@ minimatch@^5.0.1:
dependencies:
brace-expansion "^2.0.1"
minimatch@^9.0.1:
version "9.0.3"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
dependencies:
brace-expansion "^2.0.1"
minimist-options@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
@@ -14980,6 +15124,17 @@ minipass-fetch@^1.3.0, minipass-fetch@^1.3.2:
optionalDependencies:
encoding "^0.1.12"
minipass-fetch@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.4.tgz#4d4d9b9f34053af6c6e597a64be8e66e42bf45b7"
integrity sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==
dependencies:
minipass "^7.0.3"
minipass-sized "^1.0.3"
minizlib "^2.1.2"
optionalDependencies:
encoding "^0.1.13"
minipass-flush@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373"
@@ -15022,13 +15177,18 @@ minipass@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.2, minipass@^7.0.3:
version "7.0.4"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c"
integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==
minizlib@^1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
dependencies:
minipass "^2.9.0"
minizlib@^2.0.0, minizlib@^2.1.1:
minizlib@^2.0.0, minizlib@^2.1.1, minizlib@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
dependencies:
@@ -15057,7 +15217,7 @@ mkdirp@*:
version "3.0.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50"
mkdirp@^0.5.1, mkdirp@^0.5.5:
mkdirp@^0.5.5:
version "0.5.6"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
dependencies:
@@ -15253,9 +15413,10 @@ near-api-js@^0.44.2:
text-encoding-utf-8 "^1.0.2"
tweetnacl "^1.0.1"
negotiator@0.6.3, negotiator@^0.6.2:
negotiator@0.6.3, negotiator@^0.6.2, negotiator@^0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
neo-async@^2.6.2:
version "2.6.2"
@@ -15390,36 +15551,21 @@ node-gyp-build@^4.2.0, node-gyp-build@^4.3.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055"
node-gyp@^5.0.2:
version "5.1.1"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.1.1.tgz#eb915f7b631c937d282e33aed44cb7a025f62a3e"
node-gyp@10.0.1, node-gyp@^5.0.2, node-gyp@^7.1.0:
version "10.0.1"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-10.0.1.tgz#205514fc19e5830fa991e4a689f9e81af377a966"
integrity sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==
dependencies:
env-paths "^2.2.0"
glob "^7.1.4"
graceful-fs "^4.2.2"
mkdirp "^0.5.1"
nopt "^4.0.1"
npmlog "^4.1.2"
request "^2.88.0"
rimraf "^2.6.3"
semver "^5.7.1"
tar "^4.4.12"
which "^1.3.1"
node-gyp@^7.1.0:
version "7.1.2"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae"
dependencies:
env-paths "^2.2.0"
glob "^7.1.4"
graceful-fs "^4.2.3"
nopt "^5.0.0"
npmlog "^4.1.2"
request "^2.88.2"
rimraf "^3.0.2"
semver "^7.3.2"
tar "^6.0.2"
which "^2.0.2"
exponential-backoff "^3.1.1"
glob "^10.3.10"
graceful-fs "^4.2.6"
make-fetch-happen "^13.0.0"
nopt "^7.0.0"
proc-log "^3.0.0"
semver "^7.3.5"
tar "^6.1.2"
which "^4.0.0"
node-html-parser@^5.2.0:
version "5.4.2"
@@ -15461,18 +15607,12 @@ nodemon@^2.0.20:
touch "^3.1.0"
undefsafe "^2.0.5"
nopt@^4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
nopt@^7.0.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.0.tgz#067378c68116f602f552876194fd11f1292503d7"
integrity sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==
dependencies:
abbrev "1"
osenv "^0.1.4"
nopt@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
dependencies:
abbrev "1"
abbrev "^2.0.0"
nopt@~1.0.10:
version "1.0.10"
@@ -15834,21 +15974,10 @@ ora@^6.3.0:
strip-ansi "^7.0.1"
wcwidth "^1.0.1"
os-homedir@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
osenv@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
dependencies:
os-homedir "^1.0.0"
os-tmpdir "^1.0.0"
p-cancelable@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"
@@ -16135,6 +16264,14 @@ path-root@^0.1.1:
dependencies:
path-root-regex "^0.1.0"
path-scurry@^1.10.1:
version "1.10.1"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698"
integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==
dependencies:
lru-cache "^9.1.1 || ^10.0.0"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
@@ -16253,9 +16390,10 @@ preact@10.4.1:
version "10.4.1"
resolved "https://registry.yarnpkg.com/preact/-/preact-10.4.1.tgz#9b3ba020547673a231c6cf16f0fbaef0e8863431"
prebuild-install@^7.1.0:
prebuild-install@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45"
integrity sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==
dependencies:
detect-libc "^2.0.0"
expand-template "^2.0.3"
@@ -16290,6 +16428,11 @@ pretty-format@^29.0.0, pretty-format@^29.6.3:
ansi-styles "^5.0.0"
react-is "^18.0.0"
proc-log@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8"
integrity sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@@ -17292,7 +17435,7 @@ replace-ext@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb"
request@^2.79.0, request@^2.85.0, request@^2.88.0, request@^2.88.2:
request@^2.79.0, request@^2.85.0:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
dependencies:
@@ -17440,12 +17583,6 @@ rifm@^0.7.0:
dependencies:
"@babel/runtime" "^7.3.1"
rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
dependencies:
glob "^7.1.3"
rimraf@^3.0.0, rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@@ -17634,7 +17771,7 @@ semver@^6.0.0, semver@^6.3.0, semver@^6.3.1:
version "6.3.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
semver@^7.1.1, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4:
semver@^7.1.1, semver@^7.1.3, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4:
version "7.5.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
dependencies:
@@ -17785,6 +17922,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
version "3.0.7"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
signal-exit@^4.0.1:
version "4.1.0"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
signedsource@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/signedsource/-/signedsource-1.0.0.tgz#1ddace4981798f93bd833973803d80d52e93ad6a"
@@ -17881,9 +18023,19 @@ socks-proxy-agent@^6.0.0:
debug "^4.3.3"
socks "^2.6.2"
socks@^2.3.3, socks@^2.6.2:
socks-proxy-agent@^8.0.1:
version "8.0.2"
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz#5acbd7be7baf18c46a3f293a840109a430a640ad"
integrity sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==
dependencies:
agent-base "^7.0.2"
debug "^4.3.4"
socks "^2.7.1"
socks@^2.3.3, socks@^2.6.2, socks@^2.7.1:
version "2.7.1"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55"
integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==
dependencies:
ip "^2.0.0"
smart-buffer "^4.2.0"
@@ -18107,6 +18259,13 @@ sshpk@^1.7.0:
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
ssri@^10.0.0:
version "10.0.5"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c"
integrity sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==
dependencies:
minipass "^7.0.3"
ssri@^8.0.0, ssri@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af"
@@ -18214,6 +18373,15 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
@@ -18222,14 +18390,6 @@ string-width@^1.0.1:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
@@ -18245,9 +18405,10 @@ string-width@^3.0.0, string-width@^3.1.0:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"
string-width@^5.0.0:
string-width@^5.0.0, string-width@^5.0.1, string-width@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
dependencies:
eastasianwidth "^0.2.0"
emoji-regex "^9.2.2"
@@ -18314,6 +18475,13 @@ stringify-package@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/stringify-package/-/stringify-package-1.0.1.tgz#e5aa3643e7f74d0f28628b72f3dad5cecfc3ba85"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
@@ -18332,12 +18500,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
dependencies:
ansi-regex "^4.1.0"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^7.0.1:
version "7.1.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
@@ -18538,7 +18700,7 @@ tar-stream@^2.1.4:
inherits "^2.0.3"
readable-stream "^3.1.1"
tar@^4.0.2, tar@^4.4.12:
tar@^4.0.2:
version "4.4.19"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3"
dependencies:
@@ -18561,6 +18723,18 @@ tar@^6.0.2, tar@^6.1.0, tar@^6.1.11:
mkdirp "^1.0.3"
yallist "^4.0.0"
tar@^6.1.2:
version "6.2.0"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73"
integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"
minipass "^5.0.0"
minizlib "^2.1.1"
mkdirp "^1.0.3"
yallist "^4.0.0"
temp-dir@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d"
@@ -19126,12 +19300,26 @@ unique-filename@^1.1.1:
dependencies:
unique-slug "^2.0.0"
unique-filename@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea"
integrity sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==
dependencies:
unique-slug "^4.0.0"
unique-slug@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c"
dependencies:
imurmurhash "^0.1.4"
unique-slug@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3"
integrity sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==
dependencies:
imurmurhash "^0.1.4"
unist-util-generated@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.1.tgz#e37c50af35d3ed185ac6ceacb6ca0afb28a85cae"
@@ -19997,6 +20185,13 @@ which@^2.0.1, which@^2.0.2:
dependencies:
isexe "^2.0.0"
which@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/which/-/which-4.0.0.tgz#cd60b5e74503a3fbcfbf6cd6b4138a8bae644c1a"
integrity sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==
dependencies:
isexe "^3.1.1"
wide-align@^1.1.0:
version "1.1.5"
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
@@ -20021,6 +20216,15 @@ wordwrap@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba"
@@ -20044,13 +20248,14 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
ansi-styles "^6.1.0"
string-width "^5.0.1"
strip-ansi "^7.0.1"
wrappy@1:
version "1.0.2"