Compare commits

...

6 Commits

Author SHA1 Message Date
ae9ec75983 🚥 Added service status panel scaffold 2023-06-20 11:32:16 -04:00
b8fb179ac6 🔧 Miscellaneous Fixes (#79)
* ️ Config key to expose hostname in a Docker context

* 🔧 Miscellaneous Fixes
2023-05-15 16:16:26 -04:00
94692bb6d4 71 dockerfile update (#75)
* 🐳 Fixes to the Dockerfile

* 🚢 Updated port number for UI

*  Removed the param serialization from axios calls
2023-05-15 16:13:40 -04:00
4b795aca5d ️ Config key to expose hostname in a Docker context (#77) 2023-04-27 11:38:50 -04:00
fbf6bed4fe 🐳 Fixes to the Dockerfile (#74) 2023-03-31 15:09:23 -04:00
Lars Gohr
18b18c3d81 Updated elgohr/Publish-Docker-Github-Action to a supported version (v5) (#73) 2023-03-30 21:00:12 -04:00
20 changed files with 180 additions and 108 deletions

View File

@@ -12,7 +12,7 @@ jobs:
steps: steps:
- uses: actions/checkout@master - uses: actions/checkout@master
- name: Publish to Registry - name: Publish to Registry
uses: elgohr/Publish-Docker-Github-Action@master uses: elgohr/Publish-Docker-Github-Action@v5
with: with:
name: frishi/threetwo name: frishi/threetwo
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}

View File

@@ -1,4 +1,4 @@
FROM node:17.3-alpine FROM node:18.15.0-alpine
LABEL maintainer="Rishi Ghan <rishi.ghan@gmail.com>" LABEL maintainer="Rishi Ghan <rishi.ghan@gmail.com>"
WORKDIR /threetwo WORKDIR /threetwo
@@ -9,11 +9,11 @@ COPY nodemon.json ./
COPY jsdoc.json ./ COPY jsdoc.json ./
# RUN apt-get update && apt-get install -y git python3 build-essential autoconf automake g++ libpng-dev make # RUN apt-get update && apt-get install -y git python3 build-essential autoconf automake g++ libpng-dev make
RUN apk --no-cache add g++ make libpng-dev python3 git libc6-compat autoconf automake bash libjpeg-turbo-dev libpng-dev mesa-dev mesa libxi build-base gcc libtool nasm RUN apk --no-cache add g++ make libpng-dev git python3 libc6-compat autoconf automake libjpeg-turbo-dev libpng-dev mesa-dev mesa libxi build-base gcc libtool nasm
RUN yarn --ignore-engines RUN yarn --ignore-engines
COPY . . COPY . .
EXPOSE 3050 EXPOSE 5173
ENTRYPOINT [ "npm", "start" ] ENTRYPOINT [ "npm", "start" ]

View File

@@ -40,9 +40,8 @@ For debugging and troubleshooting, you can run this app locally using these step
1. Clone this repo using `git clone https://github.com/rishighan/threetwo.git` 1. Clone this repo using `git clone https://github.com/rishighan/threetwo.git`
2. `yarn run dev` (you can ignore the warnings) 2. `yarn run dev` (you can ignore the warnings)
3. This will open `http://localhost:3050` in your default browser 3. This will open `http://localhost:5173` in your default browser
4. For testing `OPDS` functionality, create a folder called `comics` under `/src/server` and put some comics in there. The `OPDS` feed is accessed to `http://localhost:8050/api/opds` 4. Note that this is simply the UI layer and won't offer anything beyond a scaffold. You have to spin up the microservices locally to get it to work.
5. Note that this is simply the UI layer and won't offer anything beyond a scaffold. You have to spin up the microservices locally to get it to work.
## Troubleshooting ## Troubleshooting

View File

@@ -7,7 +7,7 @@
"scripts": { "scripts": {
"build": "vite build", "build": "vite build",
"dev": "rimraf dist && npm run build && vite", "dev": "rimraf dist && npm run build && vite",
"prod": "npm run build && vite", "start": "npm run build && vite",
"docs": "jsdoc -c jsdoc.json", "docs": "jsdoc -c jsdoc.json",
"storybook": "storybook dev -p 6006", "storybook": "storybook dev -p 6006",
"build-storybook": "storybook build" "build-storybook": "storybook build"
@@ -30,7 +30,7 @@
"@types/socket.io": "^3.0.2", "@types/socket.io": "^3.0.2",
"@types/socket.io-client": "^3.0.0", "@types/socket.io-client": "^3.0.0",
"@vitejs/plugin-react": "^3.1.0", "@vitejs/plugin-react": "^3.1.0",
"airdcpp-apisocket": "2.4.5-beta.1", "airdcpp-apisocket": "~2.4.5-beta.2",
"axios": "^1.3.4", "axios": "^1.3.4",
"axios-cache-interceptor": "^1.0.1", "axios-cache-interceptor": "^1.0.1",
"axios-rate-limit": "^1.3.0", "axios-rate-limit": "^1.3.0",
@@ -56,7 +56,7 @@
"react-collapsible": "^2.9.0", "react-collapsible": "^2.9.0",
"react-comic-viewer": "^0.4.0", "react-comic-viewer": "^0.4.0",
"react-day-picker": "^8.6.0", "react-day-picker": "^8.6.0",
"react-dom": "^18.1.0", "react-dom": "^18.2.0",
"react-fast-compare": "^3.2.0", "react-fast-compare": "^3.2.0",
"react-final-form": "^6.5.9", "react-final-form": "^6.5.9",
"react-final-form-arrays": "^3.1.4", "react-final-form-arrays": "^3.1.4",

View File

@@ -1,7 +1,6 @@
import axios from "axios"; import axios from "axios";
import rateLimiter from "axios-rate-limit"; import rateLimiter from "axios-rate-limit";
import { setupCache } from "axios-cache-interceptor"; import { setupCache } from "axios-cache-interceptor";
import qs from "qs";
import { import {
CV_SEARCH_SUCCESS, CV_SEARCH_SUCCESS,
CV_API_CALL_IN_PROGRESS, CV_API_CALL_IN_PROGRESS,
@@ -64,9 +63,6 @@ export const comicinfoAPICall = (options) => async (dispatch) => {
"Content-Type": "application/json", "Content-Type": "application/json",
"Access-Control-Allow-Origin": "*", "Access-Control-Allow-Origin": "*",
}, },
paramsSerializer: (params) => {
return qs.stringify(params, { arrayFormat: "repeat" });
},
}); });
switch (options.callURIAction) { switch (options.callURIAction) {

View File

@@ -34,11 +34,27 @@ import {
WANTED_COMICS_FETCHED, WANTED_COMICS_FETCHED,
VOLUMES_FETCHED, VOLUMES_FETCHED,
CV_WEEKLY_PULLLIST_FETCHED, CV_WEEKLY_PULLLIST_FETCHED,
LIBRARY_SERVICE_HEALTH,
} from "../constants/action-types"; } from "../constants/action-types";
import { success } from "react-notification-system-redux"; import { success } from "react-notification-system-redux";
import { isNil, map } from "lodash"; import { isNil, map } from "lodash";
export const getServiceStatus = (serviceName?: string) => async dispatch => {
axios
.request({
url: `${LIBRARY_SERVICE_BASE_URI}/getHealthInformation`,
method: "GET",
transformResponse: (r: string) => JSON.parse(r),
})
.then((response) => {
const { data } = response;
dispatch({
type: LIBRARY_SERVICE_HEALTH,
status: data,
});
});
};
export async function walkFolder(path: string): Promise<Array<IFolderData>> { export async function walkFolder(path: string): Promise<Array<IFolderData>> {
return axios return axios
.request<Array<IFolderData>>({ .request<Array<IFolderData>>({
@@ -127,49 +143,50 @@ export const getComicBooks = (options) => async (dispatch) => {
* @returns Nothing. * @returns Nothing.
* @param payload * @param payload
*/ */
export const importToDB = (sourceName: string, metadata?: any) => (dispatch) => { export const importToDB =
try { (sourceName: string, metadata?: any) => (dispatch) => {
const comicBookMetadata = { try {
importType: "new", const comicBookMetadata = {
payload: { importType: "new",
rawFileDetails: { payload: {
name: "", rawFileDetails: {
}, name: "",
importStatus: {
isImported: true,
tagged: false,
matchedResult: {
score: "0",
}, },
importStatus: {
isImported: true,
tagged: false,
matchedResult: {
score: "0",
},
},
sourcedMetadata: metadata || null,
acquisition: { source: { wanted: true, name: sourceName } },
}, },
sourcedMetadata: metadata || null, };
acquisition: { source: { wanted: true, name: sourceName } }, dispatch({
} type: IMS_CV_METADATA_IMPORT_CALL_IN_PROGRESS,
};
dispatch({
type: IMS_CV_METADATA_IMPORT_CALL_IN_PROGRESS,
});
return axios
.request({
url: `${LIBRARY_SERVICE_BASE_URI}/rawImportToDb`,
method: "POST",
data: comicBookMetadata,
// transformResponse: (r: string) => JSON.parse(r),
})
.then((response) => {
const { data } = response;
dispatch({
type: IMS_CV_METADATA_IMPORT_SUCCESSFUL,
importResult: data,
});
}); });
} catch (error) { return axios
dispatch({ .request({
type: IMS_CV_METADATA_IMPORT_FAILED, url: `${LIBRARY_SERVICE_BASE_URI}/rawImportToDb`,
importError: error, method: "POST",
}); data: comicBookMetadata,
} // transformResponse: (r: string) => JSON.parse(r),
}; })
.then((response) => {
const { data } = response;
dispatch({
type: IMS_CV_METADATA_IMPORT_SUCCESSFUL,
importResult: data,
});
});
} catch (error) {
dispatch({
type: IMS_CV_METADATA_IMPORT_FAILED,
importError: error,
});
}
};
export const fetchVolumeGroups = () => async (dispatch) => { export const fetchVolumeGroups = () => async (dispatch) => {
try { try {
@@ -254,24 +271,23 @@ export const fetchComicVineMatches =
* @returns {any} * @returns {any}
*/ */
export const extractComicArchive = export const extractComicArchive =
(path: string, options: any): any => (path: string, options: any): any =>
async (dispatch) => { async (dispatch) => {
dispatch({ dispatch({
type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS, type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS,
}); });
await axios({ await axios({
method: "POST", method: "POST",
url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`, url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`,
headers: { headers: {
"Content-Type": "application/json; charset=utf-8", "Content-Type": "application/json; charset=utf-8",
}, },
data: { data: {
filePath: path, filePath: path,
options, options,
}, },
}); });
}; };
/** /**
* Description * Description
@@ -349,4 +365,4 @@ export const analyzeImage =
type: IMG_ANALYSIS_DATA_FETCH_SUCCESS, type: IMG_ANALYSIS_DATA_FETCH_SUCCESS,
result: foo.data, result: foo.data,
}); });
}; };

View File

@@ -15,14 +15,15 @@ export const AirDCPPSettingsForm = (): ReactElement => {
try { try {
if (!isUndefined(hostname)) { if (!isUndefined(hostname)) {
const matches = hostname.match(hostnameRegex); const matches = hostname.match(hostnameRegex);
return (isNil(matches) && matches.length !== 0) ? hostname : "Invalid hostname; it should not contain special characters"; return isNil(matches) && matches.length !== 0
? hostname
: "Invalid hostname; it should not contain special characters";
} }
} } catch {
catch {
return null; return null;
} }
} };
const onSubmit = useCallback(async (values) => { const onSubmit = useCallback(async (values) => {
try { try {
airDCPPSettings.setSettings(values); airDCPPSettings.setSettings(values);
@@ -39,7 +40,7 @@ export const AirDCPPSettingsForm = (): ReactElement => {
airDCPPSettings.setSettings({}); airDCPPSettings.setSettings({});
dispatch(deleteSettings()); dispatch(deleteSettings());
}, []); }, []);
const validate = async () => { }; const validate = async () => {};
const initFormData = !isUndefined( const initFormData = !isUndefined(
airDCPPSettings.airDCPPState.settings.directConnect, airDCPPSettings.airDCPPState.settings.directConnect,
) )
@@ -67,13 +68,20 @@ export const AirDCPPSettingsForm = (): ReactElement => {
</span> </span>
</p> </p>
<div className="control is-expanded"> <div className="control is-expanded">
<Field <Field name="hostname" validate={hostValidator}>
name="hostname"
validate={hostValidator}>
{({ input, meta }) => ( {({ input, meta }) => (
<div> <div>
<input {...input} type="text" placeholder="AirDC++ hostname" className="input" /> <input
{meta.error && meta.touched && <span className="is-size-7 has-text-danger">{meta.error}</span>} {...input}
type="text"
placeholder="AirDC++ hostname"
className="input"
/>
{meta.error && meta.touched && (
<span className="is-size-7 has-text-danger">
{meta.error}
</span>
)}
</div> </div>
)} )}
</Field> </Field>

View File

@@ -20,7 +20,7 @@ export const PullList = ({ issues }: PullListProps): ReactElement => {
useEffect(() => { useEffect(() => {
dispatch( dispatch(
getWeeklyPullList({ getWeeklyPullList({
startDate: "2023-1-25", startDate: "2023-5-25",
pageSize: "15", pageSize: "15",
currentPage: "1", currentPage: "1",
}), }),
@@ -127,7 +127,7 @@ export const PullList = ({ issues }: PullListProps): ReactElement => {
<Slider {...settings} ref={(c) => (sliderRef = c)}> <Slider {...settings} ref={(c) => (sliderRef = c)}>
{!isNil(pullList) && {!isNil(pullList) &&
pullList && pullList &&
map(pullList, ({issue}, idx) => { map(pullList, ({ issue }, idx) => {
return ( return (
<Card <Card
key={idx} key={idx}
@@ -161,4 +161,4 @@ export const PullList = ({ issues }: PullListProps): ReactElement => {
); );
}; };
export default PullList; export default PullList;

View File

@@ -125,7 +125,7 @@ export const RecentlyImported = ({
<dd className="is-size-9"> <dd className="is-size-9">
<dl> <dl>
<span className="icon custom-icon"> <span className="icon custom-icon">
<img src={`/img/${icon}`} /> <img src={`/src/client/assets/img/${icon}`} />
</span> </span>
</dl> </dl>
<dl> <dl>

View File

@@ -73,7 +73,7 @@ export const LibraryGrid = (libraryGridProps: ILibraryGridProps) => {
<div className="content is-flex is-flex-direction-row"> <div className="content is-flex is-flex-direction-row">
{!isEmpty(sourcedMetadata.comicvine) && ( {!isEmpty(sourcedMetadata.comicvine) && (
<span className="icon cv-icon is-small"> <span className="icon cv-icon is-small">
<img src="/dist/img/cvlogo.svg" /> <img src="/src/client/assets/img/cvlogo.svg" />
</span> </span>
)} )}
{isNil(rawFileDetails) && ( {isNil(rawFileDetails) && (

View File

@@ -85,7 +85,7 @@ const Navbar: React.FunctionComponent = (props) => {
{downloadProgressTick && <div className="pulsating-circle"></div>} {downloadProgressTick && <div className="pulsating-circle"></div>}
</a> </a>
{!isUndefined(downloadProgressTick) ? ( {!isUndefined(downloadProgressTick) ? (
<div className="navbar-dropdown is-right"> <div className="navbar-dropdown is-right is-boxed">
<a className="navbar-item"> <a className="navbar-item">
<DownloadProgressTick data={downloadProgressTick} /> <DownloadProgressTick data={downloadProgressTick} />
</a> </div> </a> </div>
@@ -98,7 +98,7 @@ const Navbar: React.FunctionComponent = (props) => {
<a className="navbar-link is-arrowless has-text-success"> <a className="navbar-link is-arrowless has-text-success">
<i className="fa-solid fa-bolt"></i> <i className="fa-solid fa-bolt"></i>
</a> </a>
<div className="navbar-dropdown mt-3 pt-4 pr-2 pl-2 is-right airdcpp-status is-boxed"> <div className="navbar-dropdown pr-2 pl-2 is-right airdcpp-status is-boxed">
{/* AirDC++ Session Information */} {/* AirDC++ Session Information */}
<p> <p>

View File

@@ -1,4 +1,4 @@
import React, { useMemo, useCallback, ReactElement } from "react"; import React, { useCallback, ReactElement } from "react";
import { isNil, isEmpty } from "lodash"; import { isNil, isEmpty } from "lodash";
import { IExtractedComicBookCoverFile, RootState } from "threetwo-ui-typings"; import { IExtractedComicBookCoverFile, RootState } from "threetwo-ui-typings";
import { importToDB } from "../actions/fileops.actions"; import { importToDB } from "../actions/fileops.actions";

View File

@@ -0,0 +1,25 @@
import React, { ReactElement } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useEffect } from "react";
import { getServiceStatus } from "../../actions/fileops.actions";
export const ServiceStatuses = (): ReactElement => {
const serviceStatus = useSelector(
(state: RootState) => state.fileOps.libraryServiceStatus,
);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getServiceStatus());
}, []);
return (
<div className="is-clearfix">
<div className="mt-4">
<h3 className="title">Core Services</h3>
<h6 className="subtitle has-text-grey-light">
Statuses for core services
</h6>
</div>
<pre>{JSON.stringify(serviceStatus, null, 2)}</pre>
</div>
);
};

View File

@@ -2,6 +2,7 @@ import React, { useState, ReactElement } from "react";
import { AirDCPPSettingsForm } from "./AirDCPPSettings/AirDCPPSettingsForm"; import { AirDCPPSettingsForm } from "./AirDCPPSettings/AirDCPPSettingsForm";
import { AirDCPPHubsForm } from "./AirDCPPSettings/AirDCPPHubsForm"; import { AirDCPPHubsForm } from "./AirDCPPSettings/AirDCPPHubsForm";
import { SystemSettingsForm } from "./SystemSettings/SystemSettingsForm"; import { SystemSettingsForm } from "./SystemSettings/SystemSettingsForm";
import { ServiceStatuses } from "./ServiceStatuses/ServiceStatuses";
import settingsObject from "../constants/settings/settingsMenu.json"; import settingsObject from "../constants/settings/settingsMenu.json";
import { isUndefined, map } from "lodash"; import { isUndefined, map } from "lodash";
@@ -22,6 +23,10 @@ export const Settings = (props: ISettingsProps): ReactElement => {
</div> </div>
), ),
}, },
{
id: "core-service",
content: <ServiceStatuses />,
},
{ {
id: "flushdb", id: "flushdb",
content: ( content: (

View File

@@ -139,4 +139,7 @@ export const SETTINGS_DB_FLUSH_SUCCESS = "SETTINGS_DB_FLUSH_SUCCESS";
// Metron Metadata // Metron Metadata
export const METRON_DATA_FETCH_SUCCESS = "METRON_DATA_FETCH_SUCCESS"; export const METRON_DATA_FETCH_SUCCESS = "METRON_DATA_FETCH_SUCCESS";
export const METRON_DATA_FETCH_IN_PROGRESS = "METRON_DATA_FETCH_IN_PROGRESS"; export const METRON_DATA_FETCH_IN_PROGRESS = "METRON_DATA_FETCH_IN_PROGRESS";
export const METRON_DATA_FETCH_ERROR = "METRON_DATA_FETCH_ERROR"; export const METRON_DATA_FETCH_ERROR = "METRON_DATA_FETCH_ERROR";
// service health statuses
export const LIBRARY_SERVICE_HEALTH = "LIBRARY_SERVICE_HEALTH";

View File

@@ -8,6 +8,7 @@ export const hostURIBuilder = (options: Record<string, string>): string => {
options.apiPath options.apiPath
); );
}; };
console.log(import.meta);
export const CORS_PROXY_SERVER_URI = hostURIBuilder({ export const CORS_PROXY_SERVER_URI = hostURIBuilder({
protocol: "http", protocol: "http",

View File

@@ -57,6 +57,21 @@
}, },
{ {
"id": 4, "id": 4,
"category": "statuses",
"displayName": "Service Status",
"children": [
{
"id": "core-service",
"displayName": "Core Services"
},
{
"id": "metadata-service",
"displayName": "Metadata Services"
}
]
},
{
"id": 5,
"category": "system", "category": "system",
"displayName": "System", "displayName": "System",
"children": [ "children": [
@@ -67,7 +82,7 @@
] ]
}, },
{ {
"id": 5, "id": 6,
"category": "acknowledgments", "category": "acknowledgments",
"displayName": "Acknowledgments", "displayName": "Acknowledgments",
"children": [ "children": [

View File

@@ -30,6 +30,8 @@ import {
SS_SEARCH_RESULTS_FETCHED_SPECIAL, SS_SEARCH_RESULTS_FETCHED_SPECIAL,
VOLUMES_FETCHED, VOLUMES_FETCHED,
COMICBOOK_EXTRACTION_SUCCESS, COMICBOOK_EXTRACTION_SUCCESS,
LIBRARY_SERVICE_HEALTH,
HEALTH_STATUS_TICK,
} from "../constants/action-types"; } from "../constants/action-types";
import { removeLeadingPeriod } from "../shared/utils/formatting.utils"; import { removeLeadingPeriod } from "../shared/utils/formatting.utils";
import { LIBRARY_SERVICE_HOST } from "../constants/endpoints"; import { LIBRARY_SERVICE_HOST } from "../constants/endpoints";
@@ -58,6 +60,7 @@ const initialState = {
librarySearchResultCount: 0, librarySearchResultCount: 0,
libraryQueueResults: [], libraryQueueResults: [],
librarySearchError: {}, librarySearchError: {},
libraryServiceStatus: {},
}; };
function fileOpsReducer(state = initialState, action) { function fileOpsReducer(state = initialState, action) {
@@ -153,13 +156,13 @@ function fileOpsReducer(state = initialState, action) {
} }
case LS_COVER_EXTRACTED: { case LS_COVER_EXTRACTED: {
console.log("BASH", action); console.log("BASH", action);
if(state.recentComics.length === 5) { if (state.recentComics.length === 5) {
state.recentComics.pop(); state.recentComics.pop();
} }
return { return {
...state, ...state,
librarySearchResultCount: state.librarySearchResultCount + 1, librarySearchResultCount: state.librarySearchResultCount + 1,
recentComics: [...state.recentComics, action.result.data.importResult] recentComics: [...state.recentComics, action.result.data.importResult],
}; };
} }
@@ -271,7 +274,12 @@ function fileOpsReducer(state = initialState, action) {
SSCallInProgress: false, SSCallInProgress: false,
}; };
} }
case LIBRARY_SERVICE_HEALTH: {
return {
...state,
libraryServiceStatus: action.status,
};
}
case FILEOPS_STATE_RESET: { case FILEOPS_STATE_RESET: {
return { return {
...state, ...state,
@@ -283,4 +291,4 @@ function fileOpsReducer(state = initialState, action) {
} }
} }
export default fileOpsReducer; export default fileOpsReducer;

View File

@@ -6,6 +6,7 @@ export default defineConfig({
publicDir: "public", publicDir: "public",
base: "", base: "",
build: "esnext", build: "esnext",
server: { host: true },
plugins: [ plugins: [
nodeResolve({ nodeResolve({
// browser: true // browser: true

View File

@@ -4083,12 +4083,12 @@ aggregate-error@^3.0.0:
clean-stack "^2.0.0" clean-stack "^2.0.0"
indent-string "^4.0.0" indent-string "^4.0.0"
airdcpp-apisocket@2.4.5-beta.1: airdcpp-apisocket@~2.4.5-beta.2:
version "2.4.5-beta.1" version "2.5.0-beta.2"
resolved "https://registry.yarnpkg.com/airdcpp-apisocket/-/airdcpp-apisocket-2.4.5-beta.1.tgz#f85674e98b7b733d91ee1e9b751ea9e757239964" resolved "https://registry.yarnpkg.com/airdcpp-apisocket/-/airdcpp-apisocket-2.5.0-beta.2.tgz#062541095de75775bfa92b5cb4e785674beb8986"
integrity sha512-Esa+p72zA9gMWDdlOkEWinvOhu01WvV9CCOvmQUrwLZXCNtT+70QBQqAY+vh0FMYrpkiH8Ync7ues4ERHPnxyw== integrity sha512-N/+39wYrZc/2N5CaZPG8kUSMu9shGGmLqR/0WQbJ1NiHF5VHcifN27ioldijN10KGfssFvTZBjV93m+D8ADDkQ==
dependencies: dependencies:
chalk "^5.1.2" chalk "^4.1.2"
events "^3.3.0" events "^3.3.0"
invariant "^2.2.4" invariant "^2.2.4"
is-in-browser "^2.0.0" is-in-browser "^2.0.0"
@@ -5292,11 +5292,6 @@ chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2:
ansi-styles "^4.1.0" ansi-styles "^4.1.0"
supports-color "^7.1.0" supports-color "^7.1.0"
chalk@^5.1.2:
version "5.2.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3"
integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==
char-regex@^1.0.2: char-regex@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
@@ -11497,7 +11492,7 @@ react-docgen@^5.4.0:
node-dir "^0.1.10" node-dir "^0.1.10"
strip-indent "^3.0.0" strip-indent "^3.0.0"
react-dom@^18.1.0: react-dom@^18.2.0:
version "18.2.0" version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==