feat(ui): add roarr logger

This commit is contained in:
psychedelicious 2023-04-29 16:50:54 +10:00
parent 8d837558ac
commit a4c258e9ec
15 changed files with 328 additions and 32 deletions

View File

@ -65,6 +65,7 @@
"@emotion/styled": "^11.10.6",
"@fontsource/inter": "^4.5.15",
"@reduxjs/toolkit": "^1.9.5",
"@roarr/browser-log-writer": "^1.1.5",
"chakra-ui-contextmenu": "^1.0.5",
"dateformat": "^5.0.3",
"formik": "^2.2.9",
@ -93,17 +94,19 @@
"redux-deep-persist": "^1.0.7",
"redux-dynamic-middlewares": "^2.2.0",
"redux-persist": "^6.0.0",
"roarr": "^7.15.0",
"socket.io-client": "^4.6.0",
"use-image": "^1.1.0",
"uuid": "^9.0.0"
},
"peerDependencies": {
"@chakra-ui/cli": "^2.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"ts-toolbelt": "^9.6.0",
"@chakra-ui/cli": "^2.4.0"
"ts-toolbelt": "^9.6.0"
},
"devDependencies": {
"@chakra-ui/cli": "^2.4.0",
"@types/dateformat": "^5.0.0",
"@types/lodash-es": "^4.14.194",
"@types/node": "^18.16.2",
@ -116,7 +119,6 @@
"@vitejs/plugin-react-swc": "^3.3.0",
"axios": "^1.4.0",
"babel-plugin-transform-imports": "^2.0.0",
"@chakra-ui/cli": "^2.4.0",
"concurrently": "^8.0.1",
"eslint": "^8.39.0",
"eslint-config-prettier": "^8.8.0",

View File

@ -530,7 +530,8 @@
"resetWebUI": "Reset Web UI",
"resetWebUIDesc1": "Resetting the web UI only resets the browser's local cache of your images and remembered settings. It does not delete any images from disk.",
"resetWebUIDesc2": "If images aren't showing up in the gallery or something else isn't working, please try resetting before submitting an issue on GitHub.",
"resetComplete": "Web UI has been reset. Refresh the page to reload."
"resetComplete": "Web UI has been reset. Refresh the page to reload.",
"consoleLogLevel": "Console Log Level"
},
"toast": {
"serverError": "Server Error",

View File

@ -27,6 +27,7 @@ import { PartialAppConfig } from 'app/types/invokeai';
import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys';
import { configChanged } from 'features/system/store/configSlice';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { useLogger } from 'app/logging/useLogger';
const DEFAULT_CONFIG = {};
@ -37,6 +38,7 @@ interface Props extends PropsWithChildren {
const App = ({ config = DEFAULT_CONFIG, children }: Props) => {
useToastWatcher();
useGlobalHotkeys();
const log = useLogger();
const currentTheme = useAppSelector((state) => state.ui.currentTheme);
@ -50,9 +52,9 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => {
const dispatch = useAppDispatch();
useEffect(() => {
console.log('Received config: ', config);
log.info({ namespace: 'App', data: config }, 'Received config');
dispatch(configChanged(config));
}, [dispatch, config]);
}, [dispatch, config, log]);
useEffect(() => {
setColorMode(['light'].includes(currentTheme) ? 'light' : 'dark');

View File

@ -0,0 +1,93 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppSelector } from 'app/store/storeHooks';
import { systemSelector } from 'features/system/store/systemSelectors';
import { isEqual } from 'lodash-es';
import { useEffect } from 'react';
import { LogLevelName, ROARR, Roarr } from 'roarr';
import { createLogWriter } from '@roarr/browser-log-writer';
// Base logging context includes only the package name
const baseContext = { package: '@invoke-ai/invoke-ai-ui' };
// Create browser log writer
ROARR.write = createLogWriter();
// Module-scoped logger - can be imported and used anywhere
export let log = Roarr.child(baseContext);
// Translate human-readable log levels to numbers, used for log filtering
export const LOG_LEVEL_MAP: Record<LogLevelName, number> = {
trace: 10,
debug: 20,
info: 30,
warn: 40,
error: 50,
fatal: 60,
};
export const VALID_LOG_LEVELS = [
'trace',
'debug',
'info',
'warn',
'error',
'fatal',
'none',
] as const;
export type InvokeLogLevel = (typeof VALID_LOG_LEVELS)[number];
const selector = createSelector(
systemSelector,
(system) => {
const { app_version, consoleLogLevel } = system;
return {
version: app_version,
consoleLogLevel,
};
},
{
memoizeOptions: {
resultEqualityCheck: isEqual,
},
}
);
export const useLogger = () => {
const { version, consoleLogLevel } = useAppSelector(selector);
// The provided Roarr browser log writer uses localStorage to config logging to console
useEffect(() => {
if (consoleLogLevel === 'none') {
// Disable console log output
localStorage.setItem('ROARR_LOG', 'false');
} else {
// Enable console log output
localStorage.setItem('ROARR_LOG', 'true');
// Use a filter to show only logs of the given level
localStorage.setItem(
'ROARR_FILTER',
`context.logLevel:>=${LOG_LEVEL_MAP[consoleLogLevel]}`
);
}
ROARR.write = createLogWriter();
}, [consoleLogLevel]);
// Update the module-scoped logger context as needed
useEffect(() => {
const newContext: Record<string, any> = {
...baseContext,
};
if (version) {
newContext.version = version;
}
log = Roarr.child(newContext);
}, [version]);
// Use the logger within components - no different than just importing it directly
return log;
};

View File

@ -28,7 +28,7 @@ import { lightboxDenylist } from 'features/lightbox/store/lightboxPersistDenylis
import { modelsDenylist } from 'features/system/store/modelsPersistDenylist';
import { nodesDenylist } from 'features/nodes/store/nodesPersistDenylist';
import { postprocessingDenylist } from 'features/parameters/store/postprocessingPersistDenylist';
import { systemDenylist } from 'features/system/store/systemPersistsDenylist';
import { systemDenylist } from 'features/system/store/systemPersistDenylist';
import { uiDenylist } from 'features/ui/store/uiPersistDenylist';
/**
@ -82,7 +82,6 @@ const rootPersistConfig = getPersistConfig({
'hotkeys',
'config',
],
debounce: 300,
});
const persistedReducer = persistReducer(rootPersistConfig, rootReducer);

View File

@ -23,6 +23,7 @@ import IAISelect from 'common/components/IAISelect';
import IAISwitch from 'common/components/IAISwitch';
import { systemSelector } from 'features/system/store/systemSelectors';
import {
consoleLogLevelChanged,
InProgressImageType,
setEnableImageDebugging,
setSaveIntermediatesInterval,
@ -39,8 +40,10 @@ import {
import { UIState } from 'features/ui/store/uiTypes';
import { isEqual, map } from 'lodash-es';
import { persistor } from 'app/store/persistor';
import { ChangeEvent, cloneElement, ReactElement } from 'react';
import { ChangeEvent, cloneElement, ReactElement, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { InvokeLogLevel, VALID_LOG_LEVELS } from 'app/logging/useLogger';
import { LogLevelName } from 'roarr';
const selector = createSelector(
[systemSelector, uiSelector],
@ -52,6 +55,7 @@ const selector = createSelector(
model_list,
saveIntermediatesInterval,
enableImageDebugging,
consoleLogLevel,
} = system;
const { shouldUseCanvasBetaLayout, shouldUseSliders } = ui;
@ -65,6 +69,7 @@ const selector = createSelector(
enableImageDebugging,
shouldUseCanvasBetaLayout,
shouldUseSliders,
consoleLogLevel,
};
},
{
@ -116,6 +121,7 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
enableImageDebugging,
shouldUseCanvasBetaLayout,
shouldUseSliders,
consoleLogLevel,
} = useAppSelector(selector);
/**
@ -135,6 +141,13 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
dispatch(setSaveIntermediatesInterval(value));
};
const handleLogLevelChanged = useCallback(
(e: ChangeEvent<HTMLSelectElement>) => {
dispatch(consoleLogLevelChanged(e.target.value as LogLevelName));
},
[dispatch]
);
return (
<>
{cloneElement(children, {
@ -211,6 +224,12 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
<Heading size="sm" style={{ fontWeight: 'bold' }}>
Developer
</Heading>
<IAISelect
label={t('settings.consoleLogLevel')}
onChange={handleLogLevelChanged}
value={consoleLogLevel}
validValues={VALID_LOG_LEVELS.concat()}
/>
<IAISwitch
label={t('settings.enableImageDebugging')}
isChecked={enableImageDebugging}

View File

@ -21,6 +21,8 @@ import { makeToast } from '../hooks/useToastWatcher';
import { sessionCanceled, sessionInvoked } from 'services/thunks/session';
import { receivedModels } from 'services/thunks/model';
import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice';
import { LogLevelName } from 'roarr';
import { InvokeLogLevel, VALID_LOG_LEVELS } from 'app/logging/useLogger';
export type LogLevel = 'info' | 'warning' | 'error';
@ -97,6 +99,10 @@ export interface SystemState
* Whether or not the OpenAPI schema was received and parsed
*/
wasSchemaParsed: boolean;
/**
* The console output logging level
*/
consoleLogLevel: InvokeLogLevel;
}
const initialSystemState: SystemState = {
@ -149,6 +155,7 @@ const initialSystemState: SystemState = {
// disabledFeatures: [],
wereModelsReceived: false,
wasSchemaParsed: false,
consoleLogLevel: 'info',
};
export const systemSlice = createSlice({
@ -346,6 +353,9 @@ export const systemSlice = createSlice({
subscribedNodeIdsSet: (state, action: PayloadAction<string[]>) => {
state.subscribedNodeIds = action.payload;
},
consoleLogLevelChanged: (state, action: PayloadAction<LogLevelName>) => {
state.consoleLogLevel = action.payload;
},
},
extraReducers(builder) {
/**
@ -353,7 +363,6 @@ export const systemSlice = createSlice({
*/
builder.addCase(socketSubscribed, (state, action) => {
state.sessionId = action.payload.sessionId;
console.log(`Subscribed to session ${action.payload.sessionId}`);
});
/**
@ -374,7 +383,7 @@ export const systemSlice = createSlice({
state.log.push({
timestamp,
message: `Connected to server`,
level: 'info',
level: 'error',
});
});
@ -562,6 +571,7 @@ export const {
scheduledCancelAborted,
cancelTypeChanged,
subscribedNodeIdsSet,
consoleLogLevelChanged,
} = systemSlice.actions;
export default systemSlice.reducer;

View File

@ -6,13 +6,9 @@ import {
ServerToClientEvents,
} from 'services/events/types';
import {
generatorProgress,
invocationComplete,
invocationError,
invocationStarted,
socketConnected,
socketDisconnected,
socketReset,
socketSubscribed,
socketUnsubscribed,
} from './actions';
@ -25,7 +21,6 @@ import { getTimestamp } from 'common/util/getTimestamp';
import {
sessionInvoked,
isFulfilledSessionCreatedAction,
sessionCanceled,
} from 'services/thunks/session';
import { OpenAPI } from 'services/api';
import { receivedModels } from 'services/thunks/model';
@ -33,6 +28,9 @@ import { receivedOpenAPISchema } from 'services/thunks/schema';
import { isImageOutput } from 'services/types/guards';
import { imageReceived, thumbnailReceived } from 'services/thunks/image';
import { setEventListeners } from 'services/events/util/setEventListeners';
import { log } from 'app/logging/useLogger';
const moduleLog = log.child({ namespace: 'socketio' });
export const socketMiddleware = () => {
let areListenersSet = false;
@ -91,6 +89,8 @@ export const socketMiddleware = () => {
// Must happen in middleware to get access to `dispatch`
if (!areListenersSet) {
socket.on('connect', () => {
moduleLog.debug('Connected');
dispatch(socketConnected({ timestamp: getTimestamp() }));
const { results, uploads, models, nodes, config, system } =
@ -116,7 +116,10 @@ export const socketMiddleware = () => {
}
if (system.sessionId) {
console.log(`Re-subscribing to session ${system.sessionId}`);
const sessionLog = moduleLog.child({ sessionId: system.sessionId });
sessionLog.debug('Re-subscribe');
socket.emit('subscribe', { session: system.sessionId });
dispatch(
socketSubscribed({
@ -124,11 +127,12 @@ export const socketMiddleware = () => {
timestamp: getTimestamp(),
})
);
setEventListeners({ socket, store });
setEventListeners({ socket, store, sessionLog });
}
});
socket.on('disconnect', () => {
moduleLog.debug('Disconnected');
dispatch(socketDisconnected({ timestamp: getTimestamp() }));
});
@ -140,6 +144,8 @@ export const socketMiddleware = () => {
// Everything else only happens once we have created a session
if (isFulfilledSessionCreatedAction(action)) {
const sessionId = action.payload.id;
const sessionLog = moduleLog.child({ sessionId });
const oldSessionId = getState().system.sessionId;
// const subscribedNodeIds = getState().system.subscribedNodeIds;
@ -152,6 +158,9 @@ export const socketMiddleware = () => {
// };
if (oldSessionId) {
sessionLog
.child({ oldSessionId })
.debug('Unsubscribe from old session');
// Unsubscribe when invocations complete
socket.emit('unsubscribe', {
session: oldSessionId,
@ -176,8 +185,7 @@ export const socketMiddleware = () => {
});
}
const sessionId = action.payload.id;
sessionLog.debug('Subscribe');
socket.emit('subscribe', { session: sessionId });
dispatch(
socketSubscribed({
@ -185,7 +193,7 @@ export const socketMiddleware = () => {
timestamp: getTimestamp(),
})
);
setEventListeners({ socket, store });
setEventListeners({ socket, store, sessionLog });
// Finally we actually invoke the session, starting processing
dispatch(sessionInvoked({ sessionId }));

View File

@ -10,29 +10,36 @@ import {
invocationStarted,
} from '../actions';
import { ClientToServerEvents, ServerToClientEvents } from '../types';
import { Logger } from 'roarr';
import { JsonObject } from 'roarr/dist/types';
type SetEventListenersArg = {
socket: Socket<ServerToClientEvents, ClientToServerEvents>;
store: MiddlewareAPI<AppDispatch, RootState>;
sessionLog: Logger<JsonObject>;
};
export const setEventListeners = (arg: SetEventListenersArg) => {
const { socket, store } = arg;
const { socket, store, sessionLog } = arg;
const { dispatch, getState } = store;
// Set up listeners for the present subscription
socket.on('invocation_started', (data) => {
sessionLog.child({ data }).info('Invocation started');
dispatch(invocationStarted({ data, timestamp: getTimestamp() }));
});
socket.on('generator_progress', (data) => {
sessionLog.child({ data }).trace('Generator progress');
dispatch(generatorProgress({ data, timestamp: getTimestamp() }));
});
socket.on('invocation_error', (data) => {
sessionLog.child({ data }).error('Invocation error');
dispatch(invocationError({ data, timestamp: getTimestamp() }));
});
socket.on('invocation_complete', (data) => {
sessionLog.child({ data }).info('Invocation complete');
const sessionId = data.graph_execution_state_id;
const { cancelType, isCancelScheduled } = getState().system;

View File

@ -1,8 +1,11 @@
import { log } from 'app/logging/useLogger';
import { createAppAsyncThunk } from 'app/store/storeUtils';
import { ImagesService } from 'services/api';
export const IMAGES_PER_PAGE = 20;
const galleryLog = log.child({ namespace: 'gallery' });
export const receivedResultImagesPage = createAppAsyncThunk(
'results/receivedResultImagesPage',
async (_arg, { getState }) => {
@ -12,6 +15,8 @@ export const receivedResultImagesPage = createAppAsyncThunk(
perPage: IMAGES_PER_PAGE,
});
galleryLog.info({ response }, 'Received page of results images');
return response;
}
);
@ -25,6 +30,8 @@ export const receivedUploadImagesPage = createAppAsyncThunk(
perPage: IMAGES_PER_PAGE,
});
galleryLog.info({ response }, 'Received page of uploads images');
return response;
}
);

View File

@ -1,10 +1,13 @@
import { isFulfilled, isRejected } from '@reduxjs/toolkit';
import { log } from 'app/logging/useLogger';
import { createAppAsyncThunk } from 'app/store/storeUtils';
import { imageSelected } from 'features/gallery/store/gallerySlice';
import { clamp } from 'lodash-es';
import { ImagesService } from 'services/api';
import { getHeaders } from 'services/util/getHeaders';
const imagesLog = log.child({ namespace: 'image' });
type ImageReceivedArg = Parameters<(typeof ImagesService)['getImage']>[0];
/**
@ -14,6 +17,9 @@ export const imageReceived = createAppAsyncThunk(
'api/imageReceived',
async (arg: ImageReceivedArg, _thunkApi) => {
const response = await ImagesService.getImage(arg);
imagesLog.info({ arg, response }, 'Received image');
return response;
}
);
@ -29,6 +35,9 @@ export const thumbnailReceived = createAppAsyncThunk(
'api/thumbnailReceived',
async (arg: ThumbnailReceivedArg, _thunkApi) => {
const response = await ImagesService.getThumbnail(arg);
imagesLog.info({ arg, response }, 'Received thumbnail');
return response;
}
);
@ -43,6 +52,9 @@ export const imageUploaded = createAppAsyncThunk(
async (arg: ImageUploadedArg, _thunkApi) => {
const response = await ImagesService.uploadImage(arg);
const { location } = getHeaders(response);
imagesLog.info({ arg: '<Blob>', response, location }, 'Image uploaded');
return { response, location };
}
);
@ -96,6 +108,8 @@ export const imageDeleted = createAppAsyncThunk(
const response = await ImagesService.deleteImage(arg);
imagesLog.info({ arg, response }, 'Image deleted');
return response;
}
);

View File

@ -1,14 +1,18 @@
import { log } from 'app/logging/useLogger';
import { createAppAsyncThunk } from 'app/store/storeUtils';
import { Model } from 'features/system/store/modelSlice';
import { reduce } from 'lodash-es';
import { ModelsService } from 'services/api';
const models = log.child({ namespace: 'model' });
export const IMAGES_PER_PAGE = 20;
export const receivedModels = createAppAsyncThunk(
'models/receivedModels',
async (_arg) => {
async (_) => {
const response = await ModelsService.listModels();
const deserializedModels = reduce(
response.models,
(modelsAccumulator, model, modelName) => {
@ -19,6 +23,8 @@ export const receivedModels = createAppAsyncThunk(
{} as Record<string, Model>
);
models.info({ response }, 'Received models');
return deserializedModels;
}
);

View File

@ -1,16 +1,19 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { log } from 'app/logging/useLogger';
import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice';
import { OpenAPIV3 } from 'openapi-types';
const schemaLog = log.child({ namespace: 'schema' });
export const receivedOpenAPISchema = createAsyncThunk(
'nodes/receivedOpenAPISchema',
async (_, { dispatch }): Promise<OpenAPIV3.Document> => {
const response = await fetch(`openapi.json`);
const openAPISchema = (await response.json()) as OpenAPIV3.Document;
const openAPISchema = await response.json();
console.debug('OpenAPI schema: ', openAPISchema);
schemaLog.info({ openAPISchema }, 'Received OpenAPI schema');
dispatch(parsedOpenAPISchema(openAPISchema));
dispatch(parsedOpenAPISchema(openAPISchema as OpenAPIV3.Document));
return openAPISchema;
}

View File

@ -3,6 +3,9 @@ import { SessionsService } from 'services/api';
import { buildLinearGraph as buildGenerateGraph } from 'features/nodes/util/linearGraphBuilder/buildLinearGraph';
import { isAnyOf, isFulfilled } from '@reduxjs/toolkit';
import { buildNodesGraph } from 'features/nodes/util/nodesGraphBuilder/buildNodesGraph';
import { log } from 'app/logging/useLogger';
const sessionLog = log.child({ namespace: 'session' });
export const generateGraphBuilt = createAppAsyncThunk(
'api/generateGraphBuilt',
@ -43,12 +46,12 @@ type SessionCreatedArg = {
export const sessionCreated = createAppAsyncThunk(
'api/sessionCreated',
async (arg: SessionCreatedArg, { dispatch, getState }) => {
console.log('Session created, graph: ', arg.graph);
const response = await SessionsService.createSession({
requestBody: arg.graph,
});
sessionLog.info({ arg, response }, 'Session created');
return response;
}
);
@ -74,6 +77,8 @@ export const nodeAdded = createAppAsyncThunk(
sessionId: arg.sessionId,
});
sessionLog.info({ arg, response }, 'Node added');
return response;
}
);
@ -91,6 +96,8 @@ export const sessionInvoked = createAppAsyncThunk(
all: true,
});
sessionLog.info({ arg, response }, 'Session invoked');
return response;
}
);
@ -111,6 +118,8 @@ export const sessionCanceled = createAppAsyncThunk(
sessionId,
});
sessionLog.info({ arg, response }, 'Session canceled');
return response;
}
);
@ -127,6 +136,8 @@ export const listedSessions = createAppAsyncThunk(
async (arg: SessionsListedArg, _thunkApi) => {
const response = await SessionsService.listSessions(arg);
sessionLog.info({ arg, response }, 'Sessions listed');
return response;
}
);

View File

@ -1421,6 +1421,15 @@
redux-thunk "^2.4.2"
reselect "^4.1.8"
"@roarr/browser-log-writer@^1.1.5":
version "1.1.5"
resolved "https://registry.yarnpkg.com/@roarr/browser-log-writer/-/browser-log-writer-1.1.5.tgz#755ff62ddaa297bb3488067408a7085db382352b"
integrity sha512-yLn//DRjh1/rUgZpZkwmT/5RqHYfkdOwGXWXnKBR3l/HE04DIhSVeYin3sc8aWHBa7s7WglQpYX/uw/WI6POpw==
dependencies:
boolean "^3.1.4"
globalthis "^1.0.2"
liqe "^3.6.0"
"@rollup/pluginutils@^4.2.1":
version "4.2.1"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d"
@ -2077,7 +2086,7 @@ aggregate-error@^3.0.0:
clean-stack "^2.0.0"
indent-string "^4.0.0"
ajv@^6.10.0, ajv@^6.12.4, ajv@~6.12.6:
ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.4, ajv@~6.12.6:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
@ -2307,6 +2316,11 @@ bl@^4.1.0:
inherits "^2.0.4"
readable-stream "^3.4.0"
boolean@^3.1.4:
version "3.2.0"
resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b"
integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==
boxen@^5.0.0:
version "5.1.2"
resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50"
@ -2609,7 +2623,7 @@ commander@^10.0.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
commander@^2.16.0, commander@^2.20.0, commander@^2.20.3, commander@^2.8.1:
commander@^2.16.0, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, commander@^2.8.1:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
@ -2828,6 +2842,11 @@ deepmerge@^2.1.1:
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
deepmerge@^4.2.2:
version "4.3.1"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
defaults@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
@ -3031,6 +3050,11 @@ dir-glob@^3.0.1:
dependencies:
path-type "^4.0.0"
discontinuous-range@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
integrity sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==
doctrine@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
@ -3442,11 +3466,28 @@ fast-json-stable-stringify@^2.0.0:
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
fast-json-stringify@^2.7.10:
version "2.7.13"
resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz#277aa86c2acba4d9851bd6108ed657aa327ed8c0"
integrity sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA==
dependencies:
ajv "^6.11.0"
deepmerge "^4.2.2"
rfdc "^1.2.0"
string-similarity "^4.0.1"
fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
fast-printf@^1.6.9:
version "1.6.9"
resolved "https://registry.yarnpkg.com/fast-printf/-/fast-printf-1.6.9.tgz#212f56570d2dc8ccdd057ee93d50dd414d07d676"
integrity sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==
dependencies:
boolean "^3.1.4"
fastq@^1.6.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
@ -3768,7 +3809,7 @@ globals@^13.19.0:
dependencies:
type-fest "^0.20.2"
globalthis@^1.0.3:
globalthis@^1.0.2, globalthis@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
@ -4465,6 +4506,14 @@ lint-staged@^13.2.2:
string-argv "^0.3.1"
yaml "^2.2.2"
liqe@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/liqe/-/liqe-3.6.0.tgz#2d05376e93ff9f4bfdb3e76481f6456d165b499f"
integrity sha512-CYVQr0bk5CCTkX3wW2MdyEWdr9FHLpiE/1cQXQ36Sdjn5gv7JIpm9jnkovFwiVzumw7f6JDFXpljwUY+fAcFYQ==
dependencies:
nearley "^2.20.1"
ts-error "^1.0.6"
listr2@^5.0.7:
version "5.0.8"
resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23"
@ -4714,6 +4763,11 @@ module-lookup-amd@^7.0.1:
requirejs "^2.3.5"
requirejs-config-file "^4.0.0"
moo@^0.5.0:
version "0.5.2"
resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.2.tgz#f9fe82473bc7c184b0d32e2215d3f6e67278733c"
integrity sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
@ -4734,6 +4788,16 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
nearley@^2.20.1:
version "2.20.1"
resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.20.1.tgz#246cd33eff0d012faf197ff6774d7ac78acdd474"
integrity sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==
dependencies:
commander "^2.19.0"
moo "^0.5.0"
railroad-diagrams "^1.0.0"
randexp "0.4.6"
neo-async@^2.6.0:
version "2.6.2"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
@ -5215,6 +5279,19 @@ quote-unquote@^1.0.0:
resolved "https://registry.yarnpkg.com/quote-unquote/-/quote-unquote-1.0.0.tgz#67a9a77148effeaf81a4d428404a710baaac8a0b"
integrity sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==
railroad-diagrams@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e"
integrity sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==
randexp@0.4.6:
version "0.4.6"
resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3"
integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==
dependencies:
discontinuous-range "1.0.0"
ret "~0.1.10"
rc@1.2.8, rc@^1.2.7, rc@^1.2.8:
version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
@ -5554,12 +5631,17 @@ restore-cursor@^3.1.0:
onetime "^5.1.0"
signal-exit "^3.0.2"
ret@~0.1.10:
version "0.1.15"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
reusify@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rfdc@^1.3.0:
rfdc@^1.2.0, rfdc@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
@ -5578,6 +5660,18 @@ rimraf@^3.0.2:
dependencies:
glob "^7.1.3"
roarr@^7.15.0:
version "7.15.0"
resolved "https://registry.yarnpkg.com/roarr/-/roarr-7.15.0.tgz#09b792f0cd31b4a7f91030bb1c47550ceec98ee4"
integrity sha512-CV9WefQfUXTX6wr8CrEMhfNef3sjIt9wNhE/5PNu4tNWsaoDNDXqq+OGn/RW9A1UPb0qc7FQlswXRaJJJsqn8A==
dependencies:
boolean "^3.1.4"
fast-json-stringify "^2.7.10"
fast-printf "^1.6.9"
globalthis "^1.0.2"
safe-stable-stringify "^2.4.1"
semver-compare "^1.0.0"
rollup-plugin-visualizer@^5.9.0:
version "5.9.0"
resolved "https://registry.yarnpkg.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.9.0.tgz#013ac54fb6a9d7c9019e7eb77eced673399e5a0b"
@ -5630,6 +5724,11 @@ safe-regex-test@^1.0.0:
get-intrinsic "^1.1.3"
is-regex "^1.1.4"
safe-stable-stringify@^2.4.1:
version "2.4.3"
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886"
integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==
sass-lookup@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/sass-lookup/-/sass-lookup-3.0.0.tgz#3b395fa40569738ce857bc258e04df2617c48cac"
@ -5644,6 +5743,11 @@ scheduler@^0.23.0:
dependencies:
loose-envify "^1.1.0"
semver-compare@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==
semver-diff@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b"
@ -5810,6 +5914,11 @@ string-argv@^0.3.1, string-argv@~0.3.1:
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da"
integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==
string-similarity@^4.0.1:
version "4.0.4"
resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b"
integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==
string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
@ -6032,6 +6141,11 @@ tree-kill@^1.2.2:
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
ts-error@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/ts-error/-/ts-error-1.0.6.tgz#277496f2a28de6c184cfce8dfd5cdd03a4e6b0fc"
integrity sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==
ts-graphviz@^1.5.0:
version "1.6.1"
resolved "https://registry.yarnpkg.com/ts-graphviz/-/ts-graphviz-1.6.1.tgz#f44525c048cb8c8c188b7324d2a91015fd31ceaf"