Podpora easter eggů
This commit is contained in:
parent
98f2b2a1e0
commit
7e4fa236b1
@ -35,8 +35,11 @@ WORKDIR /app
|
||||
|
||||
COPY --from=builder /build/node_modules ./node_modules
|
||||
COPY --from=builder /build/server/dist ./
|
||||
COPY server/resources ./server/resources
|
||||
COPY --from=builder /build/client/build ./public
|
||||
COPY /server/.env.production ./server/src
|
||||
# TODO tohle spadne když nebude existovat!
|
||||
COPY /server/.easter-eggs.json ./server/
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
|
@ -23,13 +23,14 @@
|
||||
"react-select-search": "^4.1.6",
|
||||
"react-snowfall": "^2.2.0",
|
||||
"react-toastify": "^10.0.4",
|
||||
"sass": "^1.80.6",
|
||||
"socket.io-client": "^4.6.1",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"scripts": {
|
||||
"copy-types": "cp -r ../types ./src",
|
||||
"start": "yarn copy-types && react-scripts start",
|
||||
"build": "yarn copy-types && react-scripts build",
|
||||
"build": "yarn copy-types && GENERATE_SOURCEMAP=false react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
|
@ -124,3 +124,45 @@
|
||||
align-items: center;
|
||||
font-size: xx-large;
|
||||
}
|
||||
|
||||
@keyframes bounce-in {
|
||||
0% {
|
||||
left: var(--start-left);
|
||||
right: var(--start-right);
|
||||
top: var(--start-top);
|
||||
bottom: var(--start-bottom);
|
||||
}
|
||||
|
||||
25% {
|
||||
left: var(--end-left);
|
||||
right: var(--end-right);
|
||||
top: var(--end-top);
|
||||
bottom: var(--end-bottom);
|
||||
}
|
||||
|
||||
50% {
|
||||
left: var(--start-left);
|
||||
right: var(--start-right);
|
||||
top: var(--start-top);
|
||||
bottom: var(--start-bottom);
|
||||
}
|
||||
|
||||
75% {
|
||||
left: var(--end-left);
|
||||
right: var(--end-right);
|
||||
top: var(--end-top);
|
||||
bottom: var(--end-bottom);
|
||||
}
|
||||
|
||||
100% {
|
||||
left: var(--start-left);
|
||||
right: var(--start-right);
|
||||
top: var(--start-top);
|
||||
bottom: var(--start-bottom);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO zjistit, zda to nedokážeme lépe - tohle je kvůli overflow easter egg obrázků, ale skrývá to úplně scrollbar
|
||||
html {
|
||||
overflow-x: hidden;
|
||||
}
|
@ -10,7 +10,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import PizzaOrderList from './components/PizzaOrderList';
|
||||
import SelectSearch, { SelectedOptionValue } from 'react-select-search';
|
||||
import 'react-select-search/style.css';
|
||||
import './App.css';
|
||||
import './App.scss';
|
||||
import { SelectSearchOption } from 'react-select-search';
|
||||
import { faCircleCheck, faNoteSticky, faTrashCan } from '@fortawesome/free-regular-svg-icons';
|
||||
import { useSettings } from './context/settings';
|
||||
@ -22,12 +22,25 @@ import { getData, errorHandler, getQrUrl } from './api/Api';
|
||||
import { addChoice, removeChoices, removeChoice, changeDepartureTime, jdemeObed, updateNote } from './api/FoodApi';
|
||||
import { getHumanDateTime } from './Utils';
|
||||
import NoteModal from './components/modals/NoteModal';
|
||||
import { useEasterEgg } from './context/eggs';
|
||||
import { getImage } from './api/EasterEggApi';
|
||||
|
||||
const EVENT_CONNECT = "connect"
|
||||
|
||||
// Fixní styl pro všechny easter egg obrázky
|
||||
const EASTER_EGG_STYLE = {
|
||||
zIndex: 1,
|
||||
animationName: "bounce-in",
|
||||
animationTimingFunction: "ease"
|
||||
}
|
||||
|
||||
// Výchozí doba trvání animace v sekundách, pokud není přetíženo v konfiguračním JSONu
|
||||
const EASTER_EGG_DEFAULT_DURATION = 0.75;
|
||||
|
||||
function App() {
|
||||
const auth = useAuth();
|
||||
const settings = useSettings();
|
||||
const [easterEgg, easterEggLoading] = useEasterEgg(auth);
|
||||
const [isConnected, setIsConnected] = useState<boolean>(false);
|
||||
const [data, setData] = useState<ClientData>();
|
||||
const [food, setFood] = useState<{ [key in Restaurants]?: DayMenu }>();
|
||||
@ -43,6 +56,8 @@ function App() {
|
||||
const [dayIndex, setDayIndex] = useState<number>();
|
||||
const [loadingPizzaDay, setLoadingPizzaDay] = useState<boolean>(false);
|
||||
const [noteModalOpen, setNoteModalOpen] = useState<boolean>(false);
|
||||
const [eggImage, setEggImage] = useState<Blob>();
|
||||
const eggRef = useRef<HTMLImageElement>(null);
|
||||
// Prazvláštní workaround, aby socket.io listener viděl aktuální hodnotu
|
||||
// https://medium.com/@kishorkrishna/cant-access-latest-state-inside-socket-io-listener-heres-how-to-fix-it-1522a5abebdb
|
||||
const dayIndexRef = useRef<number | undefined>(dayIndex);
|
||||
@ -161,6 +176,23 @@ function App() {
|
||||
}
|
||||
}, [handleKeyDown]);
|
||||
|
||||
// Stažení a nastavení easter egg obrázku
|
||||
useEffect(() => {
|
||||
if (auth?.login && easterEgg?.url && !eggImage) {
|
||||
getImage(easterEgg.url).then(data => {
|
||||
if (data) {
|
||||
setEggImage(data);
|
||||
// Smazání obrázku z DOMu po animaci
|
||||
setTimeout(() => {
|
||||
if (eggRef?.current) {
|
||||
eggRef.current.remove();
|
||||
}
|
||||
}, (easterEgg.duration || EASTER_EGG_DEFAULT_DURATION) * 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [auth?.login, easterEgg?.duration, easterEgg?.url, eggImage]);
|
||||
|
||||
const doAddChoice = async (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const index = Object.keys(Locations).indexOf(event.target.value as unknown as Locations);
|
||||
if (auth?.login) {
|
||||
@ -361,8 +393,11 @@ function App() {
|
||||
const noOrders = data?.pizzaDay?.orders?.length === 0;
|
||||
const canChangeChoice = dayIndex == null || data.todayWeekIndex == null || dayIndex >= data.todayWeekIndex;
|
||||
|
||||
const { path, url, startOffset, endOffset, duration, ...style } = easterEgg || {};
|
||||
|
||||
return (
|
||||
<>
|
||||
{easterEgg && eggImage && <img ref={eggRef} alt='' src={URL.createObjectURL(eggImage)} style={{ position: 'absolute', ...EASTER_EGG_STYLE, ...style, animationDuration: `${duration ?? EASTER_EGG_DEFAULT_DURATION}s` }} />}
|
||||
<Header />
|
||||
<div className='wrapper'>
|
||||
{data.isWeekend ? <h4>Užívejte víkend :)</h4> : <>
|
||||
|
@ -25,11 +25,36 @@ async function request<TResponse>(
|
||||
try {
|
||||
const response = await fetch(getBaseUrl() + url, config);
|
||||
if (!response.ok) {
|
||||
// TODO tohle je blbě, jelikož automaticky očekáváme, že v případě chyby přijde vždy JSON, což není pravda
|
||||
const json = await response.json();
|
||||
// Vyhodíme samotnou hlášku z odpovědi, odchytí si jí errorHandler
|
||||
throw new Error(json.error);
|
||||
}
|
||||
const contentType = response.headers.get("content-type");
|
||||
if (contentType && contentType.indexOf("application/json") !== -1) {
|
||||
return response.json() as TResponse;
|
||||
} else {
|
||||
return response.text() as TResponse;
|
||||
}
|
||||
} catch (e) {
|
||||
return Promise.reject(e);
|
||||
}
|
||||
}
|
||||
|
||||
async function blobRequest(
|
||||
url: string,
|
||||
config: RequestInit = {}
|
||||
): Promise<Blob> {
|
||||
config.headers = config?.headers ? new Headers(config.headers) : new Headers();
|
||||
config.headers.set("Authorization", `Bearer ${getToken()}`);
|
||||
try {
|
||||
const response = await fetch(getBaseUrl() + url, config);
|
||||
if (!response.ok) {
|
||||
const json = await response.json();
|
||||
// Vyhodíme samotnou hlášku z odpovědi, odchytí si jí errorHandler
|
||||
throw new Error(json.error);
|
||||
}
|
||||
return response.blob()
|
||||
} catch (e) {
|
||||
return Promise.reject(e);
|
||||
}
|
||||
@ -37,6 +62,7 @@ async function request<TResponse>(
|
||||
|
||||
export const api = {
|
||||
get: <TResponse>(url: string) => request<TResponse>(url),
|
||||
blobGet: (url: string) => blobRequest(url),
|
||||
post: <TBody extends BodyInit, TResponse>(url: string, body: TBody) => request<TResponse>(url, { method: 'POST', body, headers: { 'Content-Type': 'application/json' } }),
|
||||
}
|
||||
|
||||
|
12
client/src/api/EasterEggApi.ts
Normal file
12
client/src/api/EasterEggApi.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { EasterEgg } from "../types";
|
||||
import { api } from "./Api";
|
||||
|
||||
const EASTER_EGGS_API_PREFIX = '/api/easterEggs';
|
||||
|
||||
export const getEasterEgg = async (): Promise<EasterEgg | undefined> => {
|
||||
return await api.get(`${EASTER_EGGS_API_PREFIX}`);
|
||||
}
|
||||
|
||||
export const getImage = async (url: string) => {
|
||||
return await api.blobGet(`${EASTER_EGGS_API_PREFIX}/${url}`);
|
||||
}
|
@ -5,6 +5,7 @@ import { deleteToken, getToken, storeToken } from "../Utils";
|
||||
|
||||
export type AuthContextProps = {
|
||||
login?: string,
|
||||
trusted?: boolean,
|
||||
setToken: (name: string) => void,
|
||||
logout: () => void,
|
||||
}
|
||||
@ -26,6 +27,7 @@ export const useAuth = () => {
|
||||
|
||||
function useProvideAuth(): AuthContextProps {
|
||||
const [loginName, setLoginName] = useState<string | undefined>();
|
||||
const [trusted, setTrusted] = useState<boolean | undefined>();
|
||||
const [token, setToken] = useState<string | null>(getToken());
|
||||
const { decodedToken } = useJwt(token || '');
|
||||
|
||||
@ -40,8 +42,10 @@ function useProvideAuth(): AuthContextProps {
|
||||
useEffect(() => {
|
||||
if (decodedToken) {
|
||||
setLoginName((decodedToken as any).login);
|
||||
setTrusted((decodedToken as any).trusted);
|
||||
} else {
|
||||
setLoginName(undefined);
|
||||
setTrusted(undefined);
|
||||
}
|
||||
}, [decodedToken]);
|
||||
|
||||
@ -50,6 +54,7 @@ function useProvideAuth(): AuthContextProps {
|
||||
const logoutUrl = (decodedToken as any).logoutUrl;
|
||||
setToken(null);
|
||||
setLoginName(undefined);
|
||||
setTrusted(undefined);
|
||||
if (trusted && logoutUrl?.length) {
|
||||
window.location.replace(logoutUrl);
|
||||
}
|
||||
@ -57,6 +62,7 @@ function useProvideAuth(): AuthContextProps {
|
||||
|
||||
return {
|
||||
login: loginName,
|
||||
trusted,
|
||||
setToken,
|
||||
logout,
|
||||
}
|
||||
|
24
client/src/context/eggs.tsx
Normal file
24
client/src/context/eggs.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { getEasterEgg } from "../api/EasterEggApi";
|
||||
import { AuthContextProps } from "./auth";
|
||||
import { EasterEgg } from "../types";
|
||||
|
||||
export const useEasterEgg = (auth?: AuthContextProps | null): [EasterEgg | undefined, boolean] => {
|
||||
const [result, setResult] = useState<EasterEgg | undefined>();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchEasterEgg() {
|
||||
if (auth?.login) {
|
||||
setLoading(true);
|
||||
const egg = await getEasterEgg();
|
||||
setResult(egg);
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
fetchEasterEgg();
|
||||
|
||||
}, [auth?.login]);
|
||||
|
||||
return [result, loading];
|
||||
}
|
1
server/.gitignore
vendored
1
server/.gitignore
vendored
@ -4,3 +4,4 @@ data.json
|
||||
.env.production
|
||||
.env.development
|
||||
.easter-eggs.json
|
||||
/resources/easterEggs
|
@ -11,6 +11,7 @@ import { initWebsocket } from "./websocket";
|
||||
import pizzaDayRoutes from "./routes/pizzaDayRoutes";
|
||||
import foodRoutes from "./routes/foodRoutes";
|
||||
import votingRoutes from "./routes/votingRoutes";
|
||||
import easterEggRoutes from "./routes/easterEggRoutes";
|
||||
|
||||
const ENVIRONMENT = process.env.NODE_ENV || 'production';
|
||||
dotenv.config({ path: path.resolve(__dirname, `./.env.${ENVIRONMENT}`) });
|
||||
@ -128,6 +129,7 @@ app.get("/api/data", async (req, res) => {
|
||||
app.use("/api/pizzaDay", pizzaDayRoutes);
|
||||
app.use("/api/food", foodRoutes);
|
||||
app.use("/api/voting", votingRoutes);
|
||||
app.use("/api/easterEggs", easterEggRoutes);
|
||||
app.use(express.static('public'))
|
||||
|
||||
// Middleware pro zpracování chyb
|
||||
|
156
server/src/routes/easterEggRoutes.ts
Normal file
156
server/src/routes/easterEggRoutes.ts
Normal file
@ -0,0 +1,156 @@
|
||||
import express, { NextFunction } from "express";
|
||||
import { getLogin, getTrusted } from "../auth";
|
||||
import { parseToken } from "../utils";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import { EasterEgg } from "../../../types";
|
||||
|
||||
const EASTER_EGGS_JSON_PATH = path.join(__dirname, "../../.easter-eggs.json");
|
||||
const IMAGES_PATH = '../../resources/easterEggs';
|
||||
|
||||
type EasterEggsJson = {
|
||||
[key: string]: EasterEgg[]
|
||||
}
|
||||
|
||||
function generateUrl() {
|
||||
let result = '';
|
||||
const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
const charactersLength = characters.length;
|
||||
let counter = 0;
|
||||
while (counter < 32) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
counter += 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vrátí náhodně jeden z definovaných easter egg obrázků pro přihlášeného uživatele.
|
||||
*
|
||||
* @param req request
|
||||
* @param res response
|
||||
* @param next next
|
||||
* @returns náhodný easter egg obrázek, nebo 404 pokud žádný není definován
|
||||
*/
|
||||
function getEasterEggImage(req: any, res: any, next: NextFunction) {
|
||||
const login = getLogin(parseToken(req));
|
||||
const trusted = getTrusted(parseToken(req));
|
||||
try {
|
||||
// TODO vrátit!
|
||||
// if (trusted) {
|
||||
if (true) {
|
||||
if (login in easterEggs) {
|
||||
const imagePath = easterEggs[login][Math.floor(Math.random() * easterEggs[login].length)].path;
|
||||
res.sendFile(path.join(__dirname, IMAGES_PATH, imagePath));
|
||||
return;
|
||||
}
|
||||
}
|
||||
res.sendStatus(404);
|
||||
} catch (e: any) { next(e) }
|
||||
}
|
||||
|
||||
function getRandomPosition(startOffset: number, endOffset: number) {
|
||||
const choice = Math.floor(Math.random() * 4);
|
||||
|
||||
if (choice === 0) {
|
||||
// Vlevo nahoře
|
||||
return {
|
||||
left: `${startOffset}px`,
|
||||
startLeft: `${startOffset}px`,
|
||||
"--start-left": `${startOffset}px`,
|
||||
top: `${startOffset}px`,
|
||||
startTop: `${startOffset}px`,
|
||||
"--start-top": `${startOffset}px`,
|
||||
endLeft: `${endOffset}px`,
|
||||
"--end-left": `${endOffset}px`,
|
||||
endTop: `${endOffset}px`,
|
||||
"--end-top": `${endOffset}px`,
|
||||
rotate: '135deg',
|
||||
}
|
||||
} else if (choice === 1) {
|
||||
// Vpravo nahoře
|
||||
return {
|
||||
right: `${startOffset}px`,
|
||||
startRight: `${startOffset}px`,
|
||||
"--start-right": `${startOffset}px`,
|
||||
top: `${startOffset}px`,
|
||||
startTop: `${startOffset}px`,
|
||||
"--start-top": `${startOffset}px`,
|
||||
endRight: `${endOffset}px`,
|
||||
"--end-right": `${endOffset}px`,
|
||||
endTop: `${endOffset}px`,
|
||||
"--end-top": `${endOffset}px`,
|
||||
rotate: '-135deg',
|
||||
}
|
||||
} else if (choice === 2) {
|
||||
// Vpravo dole
|
||||
return {
|
||||
right: `${startOffset}px`,
|
||||
startRight: `${startOffset}px`,
|
||||
"--start-right": `${startOffset}px`,
|
||||
bottom: `${startOffset}px`,
|
||||
startBottom: `${startOffset}px`,
|
||||
"--start-bottom": `${startOffset}px`,
|
||||
endRight: `${endOffset}px`,
|
||||
"--end-right": `${endOffset}px`,
|
||||
endBottom: `${endOffset}px`,
|
||||
"--end-bottom": `${endOffset}px`,
|
||||
rotate: '-45deg',
|
||||
}
|
||||
} else if (choice === 3) {
|
||||
// Vlevo dole
|
||||
return {
|
||||
left: `${startOffset}px`,
|
||||
startLeft: `${startOffset}px`,
|
||||
"--start-left": `${startOffset}px`,
|
||||
bottom: `${startOffset}px`,
|
||||
startBottom: `${startOffset}px`,
|
||||
"--start-bottom": `${startOffset}px`,
|
||||
endLeft: `${endOffset}px`,
|
||||
"--end-left": `${endOffset}px`,
|
||||
endBottom: `${endOffset}px`,
|
||||
"--end-bottom": `${endOffset}px`,
|
||||
rotate: '45deg',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
let easterEggs: EasterEggsJson;
|
||||
|
||||
// Registrace náhodných URL pro všechny existující easter eggy
|
||||
|
||||
if (fs.existsSync(EASTER_EGGS_JSON_PATH)) {
|
||||
const content = fs.readFileSync(EASTER_EGGS_JSON_PATH, 'utf-8');
|
||||
easterEggs = JSON.parse(content);
|
||||
for (const [key, eggs] of Object.entries(easterEggs)) {
|
||||
for (const easterEgg of eggs) {
|
||||
const url = generateUrl();
|
||||
easterEgg.url = url;
|
||||
router.get(`/${url}`, async (req, res, next) => {
|
||||
return getEasterEggImage(req, res, next);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Získání náhodného easter eggu pro přihlášeného uživatele
|
||||
router.get("/", async (req, res, next) => {
|
||||
const login = getLogin(parseToken(req));
|
||||
const trusted = getTrusted(parseToken(req));
|
||||
try {
|
||||
// TODO vrátit!
|
||||
// if (trusted) {
|
||||
if (true) {
|
||||
if (easterEggs && login in easterEggs) {
|
||||
const randomEasterEgg = easterEggs[login][Math.floor(Math.random() * easterEggs[login].length)];
|
||||
const { path, startOffset, endOffset, ...strippedEasterEgg } = randomEasterEgg; // Path klient k ničemu nepotřebuje a nemá ho znát
|
||||
return res.status(200).json({ ...strippedEasterEgg, ...getRandomPosition(startOffset, endOffset) });
|
||||
}
|
||||
}
|
||||
return res.status(200).send();
|
||||
} catch (e: any) { next(e) }
|
||||
});
|
||||
|
||||
export default router;
|
@ -173,3 +173,42 @@ export enum FeatureRequest {
|
||||
UI = "Celkové vylepšení UI/UX",
|
||||
DEVELOPMENT = "Zlepšení dokumentace/postupů pro ostatní vývojáře"
|
||||
}
|
||||
|
||||
export interface EasterEgg {
|
||||
path: string;
|
||||
url: string;
|
||||
startOffset: number;
|
||||
endOffset: number;
|
||||
duration: number;
|
||||
width?: string;
|
||||
zIndex?: number;
|
||||
position?: "absolute";
|
||||
animationName?: string;
|
||||
animationDuration?: string;
|
||||
animationTimingFunction?: string;
|
||||
}
|
||||
|
||||
// TODO aktuálně se k ničemu nepoužívá
|
||||
export type AnimationPosition = {
|
||||
left?: string,
|
||||
startLeft?: string,
|
||||
"--start-left"?: string,
|
||||
right?: string,
|
||||
startRight?: string,
|
||||
"--start-right"?: string,
|
||||
top?: string,
|
||||
startTop?: string,
|
||||
"--start-top"?: string,
|
||||
bottom?: string,
|
||||
startBottom?: string,
|
||||
"--start-bottom"?: string,
|
||||
endLeft?: string,
|
||||
"--end-left"?: string,
|
||||
endRight?: string,
|
||||
"--end-right"?: string,
|
||||
endTop?: string,
|
||||
"--end-top"?: string,
|
||||
endBottom?: string,
|
||||
"--end-bottom"?: string,
|
||||
rotate?: string,
|
||||
}
|
132
yarn.lock
132
yarn.lock
@ -1876,6 +1876,95 @@
|
||||
"@nodelib/fs.scandir" "2.1.5"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@parcel/watcher-android-arm64@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz#e32d3dda6647791ee930556aee206fcd5ea0fb7a"
|
||||
integrity sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==
|
||||
|
||||
"@parcel/watcher-darwin-arm64@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz#0d9e680b7e9ec1c8f54944f1b945aa8755afb12f"
|
||||
integrity sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==
|
||||
|
||||
"@parcel/watcher-darwin-x64@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz#f9f1d5ce9d5878d344f14ef1856b7a830c59d1bb"
|
||||
integrity sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==
|
||||
|
||||
"@parcel/watcher-freebsd-x64@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz#2b77f0c82d19e84ff4c21de6da7f7d096b1a7e82"
|
||||
integrity sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==
|
||||
|
||||
"@parcel/watcher-linux-arm-glibc@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz#92ed322c56dbafa3d2545dcf2803334aee131e42"
|
||||
integrity sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==
|
||||
|
||||
"@parcel/watcher-linux-arm-musl@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz#cd48e9bfde0cdbbd2ecd9accfc52967e22f849a4"
|
||||
integrity sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==
|
||||
|
||||
"@parcel/watcher-linux-arm64-glibc@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz#7b81f6d5a442bb89fbabaf6c13573e94a46feb03"
|
||||
integrity sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==
|
||||
|
||||
"@parcel/watcher-linux-arm64-musl@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz#dcb8ff01077cdf59a18d9e0a4dff7a0cfe5fd732"
|
||||
integrity sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==
|
||||
|
||||
"@parcel/watcher-linux-x64-glibc@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz#2e254600fda4e32d83942384d1106e1eed84494d"
|
||||
integrity sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==
|
||||
|
||||
"@parcel/watcher-linux-x64-musl@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz#01fcea60fedbb3225af808d3f0a7b11229792eef"
|
||||
integrity sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==
|
||||
|
||||
"@parcel/watcher-win32-arm64@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz#87cdb16e0783e770197e52fb1dc027bb0c847154"
|
||||
integrity sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==
|
||||
|
||||
"@parcel/watcher-win32-ia32@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz#778c39b56da33e045ba21c678c31a9f9d7c6b220"
|
||||
integrity sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==
|
||||
|
||||
"@parcel/watcher-win32-x64@2.5.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz#33873876d0bbc588aacce38e90d1d7480ce81cb7"
|
||||
integrity sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==
|
||||
|
||||
"@parcel/watcher@^2.4.1":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.5.0.tgz#5c88818b12b8de4307a9d3e6dc3e28eba0dfbd10"
|
||||
integrity sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==
|
||||
dependencies:
|
||||
detect-libc "^1.0.3"
|
||||
is-glob "^4.0.3"
|
||||
micromatch "^4.0.5"
|
||||
node-addon-api "^7.0.0"
|
||||
optionalDependencies:
|
||||
"@parcel/watcher-android-arm64" "2.5.0"
|
||||
"@parcel/watcher-darwin-arm64" "2.5.0"
|
||||
"@parcel/watcher-darwin-x64" "2.5.0"
|
||||
"@parcel/watcher-freebsd-x64" "2.5.0"
|
||||
"@parcel/watcher-linux-arm-glibc" "2.5.0"
|
||||
"@parcel/watcher-linux-arm-musl" "2.5.0"
|
||||
"@parcel/watcher-linux-arm64-glibc" "2.5.0"
|
||||
"@parcel/watcher-linux-arm64-musl" "2.5.0"
|
||||
"@parcel/watcher-linux-x64-glibc" "2.5.0"
|
||||
"@parcel/watcher-linux-x64-musl" "2.5.0"
|
||||
"@parcel/watcher-win32-arm64" "2.5.0"
|
||||
"@parcel/watcher-win32-ia32" "2.5.0"
|
||||
"@parcel/watcher-win32-x64" "2.5.0"
|
||||
|
||||
"@pkgjs/parseargs@^0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
@ -3645,6 +3734,13 @@ chokidar@^3.4.2, chokidar@^3.5.2, chokidar@^3.5.3:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
chokidar@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.1.tgz#4a6dff66798fb0f72a94f616abbd7e1a19f31d41"
|
||||
integrity sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==
|
||||
dependencies:
|
||||
readdirp "^4.0.1"
|
||||
|
||||
chrome-trace-event@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
|
||||
@ -4267,6 +4363,11 @@ destroy@1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
|
||||
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
|
||||
|
||||
detect-libc@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
||||
integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
|
||||
|
||||
detect-newline@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
|
||||
@ -5811,6 +5912,11 @@ immer@^9.0.7:
|
||||
resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176"
|
||||
integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==
|
||||
|
||||
immutable@^4.0.0:
|
||||
version "4.3.7"
|
||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381"
|
||||
integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==
|
||||
|
||||
import-fresh@^3.1.0, import-fresh@^3.2.1:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
|
||||
@ -7665,6 +7771,11 @@ no-case@^3.0.4:
|
||||
lower-case "^2.0.2"
|
||||
tslib "^2.0.3"
|
||||
|
||||
node-addon-api@^7.0.0:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558"
|
||||
integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==
|
||||
|
||||
node-forge@^1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
|
||||
@ -9062,6 +9173,11 @@ readable-stream@^3.0.6:
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
readdirp@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.0.2.tgz#388fccb8b75665da3abffe2d8f8ed59fe74c230a"
|
||||
integrity sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==
|
||||
|
||||
readdirp@~3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
|
||||
@ -9339,6 +9455,17 @@ sass-loader@^12.3.0:
|
||||
klona "^2.0.4"
|
||||
neo-async "^2.6.2"
|
||||
|
||||
sass@^1.80.6:
|
||||
version "1.80.6"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.80.6.tgz#5d0aa55763984effe41e40019c9571ab73e6851f"
|
||||
integrity sha512-ccZgdHNiBF1NHBsWvacvT5rju3y1d/Eu+8Ex6c21nHp2lZGLBEtuwc415QfiI1PJa1TpCo3iXwwSRjRpn2Ckjg==
|
||||
dependencies:
|
||||
chokidar "^4.0.0"
|
||||
immutable "^4.0.0"
|
||||
source-map-js ">=0.6.2 <2.0.0"
|
||||
optionalDependencies:
|
||||
"@parcel/watcher" "^2.4.1"
|
||||
|
||||
sax@~1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
@ -9625,6 +9752,11 @@ source-list-map@^2.0.0, source-list-map@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
|
||||
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
|
||||
|
||||
"source-map-js@>=0.6.2 <2.0.0":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
|
||||
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||
|
||||
source-map-js@^1.0.1, source-map-js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
|
Loading…
x
Reference in New Issue
Block a user