1
0
mirror of https://github.com/amir20/dozzle.git synced 2025-12-24 06:28:42 +01:00

Settings to useStorage (#1602)

* Uses storage for settings

* Cleans settings

* Fixes tests for storage

* Removes store.js

* Uses ts

* Fixes tests

* Removes autoprefixer
This commit is contained in:
Amir Raminfar
2021-11-18 14:06:54 -08:00
committed by GitHub
parent 4a303d3ffa
commit e2072d35c8
12 changed files with 241 additions and 161 deletions

View File

@@ -44,12 +44,13 @@
<script lang="ts" setup>
import { Splitpanes, Pane } from "splitpanes";
import { ref, onMounted, watchEffect, toRefs, computed, watch } from "vue";
import { ref, onMounted, watchEffect, toRefs, computed } from "vue";
import { useStore } from "vuex";
import { useProgrammatic } from "@oruga-ui/oruga-next";
import hotkeys from "hotkeys-js";
import { setTitle } from "./composables/title";
import { isMobile } from "./composables/mediaQuery";
import { smallerScrollbars, lightTheme, menuWidth } from "@/composables/settings";
import FuzzySearchModal from "./components/FuzzySearchModal.vue";
import LogContainer from "./components/LogContainer.vue";
@@ -59,12 +60,9 @@ import MobileMenu from "./components/MobileMenu.vue";
const collapseNav = ref(false);
const { oruga } = useProgrammatic();
const store = useStore();
const { menuWidth } = toRefs(store.state.settings);
const { containers, authorizationNeeded } = toRefs(store.state);
const { authorizationNeeded } = toRefs(store.state);
const activeContainers = computed(() => store.getters.activeContainers);
const visibleContainers = computed(() => store.getters.visibleContainers);
const lightTheme = computed(() => store.state.settings.lightTheme);
const smallerScrollbars = computed(() => store.state.settings.smallerScrollbars);
onMounted(() => {
if (smallerScrollbars.value) {
@@ -109,8 +107,7 @@ function showFuzzySearch() {
}
function onResized(e) {
if (e.length == 2) {
const menuWidth = e[0].size;
store.dispatch("UPDATE_SETTING", { menuWidth });
menuWidth.value = e[0].size;
}
}
</script>

View File

@@ -5,6 +5,7 @@ import EventSource, { sources } from "eventsourcemock";
import debounce from "lodash.debounce";
import LogEventSource from "./LogEventSource.vue";
import LogViewer from "./LogViewer.vue";
import { settings } from "../composables/settings";
import { mocked } from "ts-jest/utils";
jest.mock("lodash.debounce", () =>
@@ -27,14 +28,17 @@ describe("<LogEventSource />", () => {
}));
mocked(debounce).mockClear();
jest.resetModules();
});
function createLogEventSource({
hourStyle = "auto",
searchFilter = null,
}: { hourStyle?: string; searchFilter?: string | null } = {}) {
function createLogEventSource(
{ searchFilter = null, hourStyle = "auto" }: { searchFilter?: string | null; hourStyle?: "auto" | "24" | "12" } = {
hourStyle: "auto",
}
) {
settings.value.hourStyle = hourStyle;
const store = createStore({
state: { searchFilter, settings: { size: "medium", showTimestamp: true, hourStyle } },
state: { searchFilter },
getters: {
allContainersById() {
return {

View File

@@ -1,7 +1,7 @@
<template>
<ul class="events" :class="settings.size">
<ul class="events" :class="size">
<li v-for="item in filtered" :key="item.key" :data-event="item.event">
<span class="date" v-if="settings.showTimestamp"> <relative-time :date="item.date"></relative-time></span>
<span class="date" v-if="showTimestamp"> <relative-time :date="item.date"></relative-time></span>
<span class="text" v-html="colorize(item.message)"></span>
</li>
</ul>
@@ -11,21 +11,23 @@
import { computed } from "vue";
import { useStore } from "vuex";
import { size, showTimestamp } from "@/composables/settings";
import RelativeTime from "./RelativeTime.vue";
import AnsiConvertor from "ansi-to-html";
const props = defineProps({
messages: Array,
messages: {
type: Array,
required: true,
},
});
const store = useStore();
const ansiConvertor = new AnsiConvertor({ escapeXML: true });
function colorize(value) {
function colorize(value: string) {
return ansiConvertor.toHtml(value).replace("&lt;mark&gt;", "<mark>").replace("&lt;/mark&gt;", "</mark>");
}
const settings = computed(() => store.state.settings);
const searchFilter = computed(() => store.state.searchFilter);
const filtered = computed(() => {
if (searchFilter && searchFilter.value) {

View File

@@ -3,8 +3,8 @@
</template>
<script lang="ts">
import { mapState } from "vuex";
import { formatRelative } from "date-fns";
import { hourStyle } from "@/composables/settings";
import enGB from "date-fns/locale/en-GB";
import enUS from "date-fns/locale/en-US";
@@ -28,9 +28,8 @@ export default {
name: "RelativeTime",
components: {},
computed: {
...mapState(["settings"]),
locale() {
const locale = styles[this.settings.hourStyle];
const locale = styles[hourStyle.value];
const oldFormatter = locale.formatRelative;
return {
...locale,

View File

@@ -1,5 +1,5 @@
<template>
<div class="search columns is-gapless is-vcentered" v-show="showSearch" v-if="settings.search">
<div class="search columns is-gapless is-vcentered" v-show="showSearch" v-if="search">
<div class="column">
<p class="control has-icons-left">
<input
@@ -21,6 +21,10 @@
</div>
</template>
<script lang="ts" setup>
import { search } from "@/composables/settings";
</script>
<script lang="ts">
import { mapActions, mapState } from "vuex";
import hotkeys from "hotkeys-js";
@@ -57,7 +61,7 @@ export default {
},
},
computed: {
...mapState(["searchFilter", "settings"]),
...mapState(["searchFilter"]),
filter: {
get() {
return this.searchFilter;

View File

@@ -0,0 +1,65 @@
import { useStorage } from "@vueuse/core";
import { computed } from "vue";
export const DOZZLE_SETTINGS_KEY = "DOZZLE_SETTINGS";
export const DEFAULT_SETTINGS: {
search: boolean;
size: "small" | "medium" | "large";
menuWidth: number;
smallerScrollbars: boolean;
showTimestamp: boolean;
showAllContainers: boolean;
lightTheme: boolean;
hourStyle: "auto" | "24" | "12";
} = {
search: true,
size: "medium",
menuWidth: 15,
smallerScrollbars: false,
showTimestamp: true,
showAllContainers: false,
lightTheme: false,
hourStyle: "auto",
};
export const settings = useStorage(DOZZLE_SETTINGS_KEY, DEFAULT_SETTINGS);
export const search = computed({
get: () => settings.value.search,
set: (value) => (settings.value.search = value),
});
export const size = computed({
get: () => settings.value.size,
set: (value) => (settings.value.size = value),
});
export const menuWidth = computed({
get: () => settings.value.menuWidth,
set: (value) => (settings.value.menuWidth = value),
});
export const smallerScrollbars = computed({
get: () => settings.value.smallerScrollbars,
set: (value) => (settings.value.smallerScrollbars = value),
});
export const showTimestamp = computed({
get: () => settings.value.showTimestamp,
set: (value) => (settings.value.showTimestamp = value),
});
export const showAllContainers = computed({
get: () => settings.value.showAllContainers,
set: (value) => (settings.value.showAllContainers = value),
});
export const lightTheme = computed({
get: () => settings.value.lightTheme,
set: (value) => (settings.value.lightTheme = value),
});
export const hourStyle = computed({
get: () => settings.value.hourStyle,
set: (value) => (settings.value.hourStyle = value),
});

View File

@@ -10,9 +10,8 @@
>.
<span v-if="hasUpdate">
New version is available! Update to
<a :href="nextRelease.html_url" class="next-release" target="_blank" rel="noreferrer noopener">{{
nextRelease.name
}}</a
<a :href="nextRelease.html_url" class="next-release" target="_blank" rel="noreferrer noopener">
{{ nextRelease.name }}</a
>.
</span>
</div>
@@ -106,55 +105,38 @@
</div>
</template>
<script lang="ts">
<script lang="ts" setup>
import { ref } from "vue";
import gt from "semver/functions/gt";
import { mapActions, mapState } from "vuex";
import config from "../store/config";
import { setTitle } from "@/composables/title";
import {
search,
lightTheme,
smallerScrollbars,
showTimestamp,
hourStyle,
showAllContainers,
size,
} from "@/composables/settings";
export default {
props: [],
name: "Settings",
data() {
return {
currentVersion: config.version,
nextRelease: null,
hasUpdate: false,
};
},
async created() {
setTitle("Settings");
const releases = await (await fetch("https://api.github.com/repos/amir20/dozzle/releases")).json();
if (this.currentVersion !== "master") {
this.hasUpdate = gt(releases[0].tag_name, this.currentVersion);
} else {
this.hasUpdate = true;
}
this.nextRelease = releases[0];
},
methods: {
...mapActions({
updateSetting: "UPDATE_SETTING",
}),
},
computed: {
...mapState(["settings"]),
...["search", "size", "smallerScrollbars", "showTimestamp", "showAllContainers", "lightTheme", "hourStyle"].reduce(
(map, name) => {
map[name] = {
get() {
return this.settings[name];
},
set(value) {
this.updateSetting({ [name]: value });
},
};
return map;
},
{}
),
},
};
setTitle("Settings");
const currentVersion = config.version;
const nextRelease = ref(null);
const hasUpdate = ref(false);
async function fetchNextRelease() {
const releases = await (await fetch("https://api.github.com/repos/amir20/dozzle/releases")).json();
if (!["dev", "master"].includes(currentVersion)) {
hasUpdate.value = gt(releases[0].tag_name, currentVersion);
} else {
hasUpdate.value = true;
}
nextRelease.value = releases[0];
}
fetchNextRelease();
</script>
<style lang="scss" scoped>
.title {

View File

@@ -1,9 +1,6 @@
import { createStore } from "vuex";
import storage from "store/dist/store.modern";
import { DEFAULT_SETTINGS, DOZZLE_SETTINGS_KEY } from "./settings";
import config from "./config";
storage.set(DOZZLE_SETTINGS_KEY, { ...DEFAULT_SETTINGS, ...storage.get(DOZZLE_SETTINGS_KEY) });
import { showAllContainers } from "@/composables/settings";
interface Container {
id: string;
@@ -31,7 +28,6 @@ const store = createStore({
containers: [] as Container[],
activeContainerIds: [] as string[],
searchFilter: null,
settings: storage.get(DOZZLE_SETTINGS_KEY),
authorizationNeeded: config.authorizationNeeded,
},
mutations: {
@@ -56,10 +52,6 @@ const store = createStore({
SET_SEARCH(state, filter) {
state.searchFilter = filter;
},
UPDATE_SETTINGS(state, newValues) {
state.settings = { ...state.settings, ...newValues };
storage.set(DOZZLE_SETTINGS_KEY, state.settings);
},
UPDATE_CONTAINER(_, { container, data }) {
for (const [key, value] of Object.entries(data)) {
container[key] = value;
@@ -99,7 +91,7 @@ const store = createStore({
allContainersById({ containers }) {
return allContainersById(containers);
},
visibleContainers({ containers, settings: { showAllContainers } }) {
visibleContainers({ containers }) {
const filter = showAllContainers ? () => true : (c: Container) => c.state === "running";
return containers.filter(filter);
},

View File

@@ -1,11 +0,0 @@
export const DOZZLE_SETTINGS_KEY = "DOZZLE_SETTINGS";
export const DEFAULT_SETTINGS = {
search: true,
size: "medium",
menuWidth: 15,
smallerScrollbars: false,
showTimestamp: true,
showAllContainers: false,
lightTheme: false,
hourStyle: "auto",
};

View File

@@ -1,9 +1,15 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
import type { Config } from "@jest/types";
const config: Config.InitialOptions = {
preset: "ts-jest",
testEnvironment: "jsdom",
testPathIgnorePatterns: ["node_modules", "<rootDir>/integration/", "<rootDir>/e2e/"],
transform: {
"^.+\\.vue$": "@vue/vue3-jest",
},
moduleNameMapper: {
"@/(.*)": ["<rootDir>/assets/$1"],
},
};
export default config;

View File

@@ -31,7 +31,6 @@
"@vitejs/plugin-vue": "^1.9.4",
"@vueuse/core": "^6.9.1",
"ansi-to-html": "^0.7.2",
"autoprefixer": "^10.4.0",
"bulma": "^0.9.3",
"date-fns": "^2.25.0",
"fuzzysort": "^1.1.4",
@@ -41,7 +40,6 @@
"sass": "^1.43.4",
"semver": "^7.3.5",
"splitpanes": "^3.0.6",
"store": "^2.0.12",
"typescript": "^4.4.4",
"unplugin-auto-import": "^0.4.14",
"unplugin-icons": "^0.12.18",
@@ -57,6 +55,7 @@
"@types/jest": "^27.0.2",
"@types/lodash.debounce": "^4.0.6",
"@types/lodash.throttle": "^4.1.6",
"@types/semver": "^7.3.9",
"@vue/compiler-sfc": "^3.2.22",
"@vue/test-utils": "^2.0.0-rc.16",
"@vue/vue3-jest": "^27.0.0-alpha.3",
@@ -68,7 +67,8 @@
"npm-run-all": "^4.1.5",
"prettier": "^2.4.1",
"release-it": "^14.11.7",
"ts-jest": "^27.0.7"
"ts-jest": "^27.0.7",
"ts-node": "^10.4.0"
},
"lint-staged": {
"*.{js,vue,css}": [

168
pnpm-lock.yaml generated
View File

@@ -12,13 +12,13 @@ specifiers:
'@types/jest': ^27.0.2
'@types/lodash.debounce': ^4.0.6
'@types/lodash.throttle': ^4.1.6
'@types/semver': ^7.3.9
'@vitejs/plugin-vue': ^1.9.4
'@vue/compiler-sfc': ^3.2.22
'@vue/test-utils': ^2.0.0-rc.16
'@vue/vue3-jest': ^27.0.0-alpha.3
'@vueuse/core': ^6.9.1
ansi-to-html: ^0.7.2
autoprefixer: ^10.4.0
bulma: ^0.9.3
date-fns: ^2.25.0
eventsourcemock: ^2.0.0
@@ -36,8 +36,8 @@ specifiers:
sass: ^1.43.4
semver: ^7.3.5
splitpanes: ^3.0.6
store: ^2.0.12
ts-jest: ^27.0.7
ts-node: ^10.4.0
typescript: ^4.4.4
unplugin-auto-import: ^0.4.14
unplugin-icons: ^0.12.18
@@ -57,7 +57,6 @@ dependencies:
'@vitejs/plugin-vue': 1.9.4_vite@2.6.14
'@vueuse/core': 6.9.1_vue@3.2.22
ansi-to-html: 0.7.2
autoprefixer: 10.4.0
bulma: 0.9.3
date-fns: 2.25.0
fuzzysort: 1.1.4
@@ -67,7 +66,6 @@ dependencies:
sass: 1.43.4
semver: 7.3.5
splitpanes: 3.0.6
store: 2.0.12
typescript: 4.4.4
unplugin-auto-import: 0.4.14_@vueuse+core@6.9.1+vite@2.6.14
unplugin-icons: 0.12.18_744c3dc4f4777e47e76c501a561da7bf
@@ -83,18 +81,20 @@ devDependencies:
'@types/jest': 27.0.2
'@types/lodash.debounce': 4.0.6
'@types/lodash.throttle': 4.1.6
'@types/semver': 7.3.9
'@vue/compiler-sfc': 3.2.22
'@vue/test-utils': 2.0.0-rc.16_vue@3.2.22
'@vue/vue3-jest': 27.0.0-alpha.3_ebe0a67a4fae2cf0b4be307c93b4d0a3
eventsourcemock: 2.0.0
husky: 7.0.4
jest: 27.3.1
jest: 27.3.1_ts-node@10.4.0
jest-serializer-vue: 2.0.2
lint-staged: 11.2.6
npm-run-all: 4.1.5
prettier: 2.4.1
release-it: 14.11.7
ts-jest: 27.0.7_2c4ca6574207836d1023f54689cc81ac
ts-node: 10.4.0_typescript@4.4.4
packages:
@@ -1319,6 +1319,18 @@ packages:
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
dev: true
/@cspotcode/source-map-consumer/0.8.0:
resolution: {integrity: sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==}
engines: {node: '>= 12'}
dev: true
/@cspotcode/source-map-support/0.7.0:
resolution: {integrity: sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==}
engines: {node: '>=12'}
dependencies:
'@cspotcode/source-map-consumer': 0.8.0
dev: true
/@iarna/toml/2.2.5:
resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==}
dev: true
@@ -1385,7 +1397,7 @@ packages:
slash: 3.0.0
dev: true
/@jest/core/27.3.1:
/@jest/core/27.3.1_ts-node@10.4.0:
resolution: {integrity: sha512-DMNE90RR5QKx0EA+wqe3/TNEwiRpOkhshKNxtLxd4rt3IZpCt+RSL+FoJsGeblRZmqdK4upHA/mKKGPPRAifhg==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
peerDependencies:
@@ -1406,7 +1418,7 @@ packages:
exit: 0.1.2
graceful-fs: 4.2.8
jest-changed-files: 27.3.0
jest-config: 27.3.1
jest-config: 27.3.1_ts-node@10.4.0
jest-haste-map: 27.3.1
jest-message-util: 27.3.1
jest-regex-util: 27.0.6
@@ -1744,6 +1756,22 @@ packages:
engines: {node: '>= 6'}
dev: true
/@tsconfig/node10/1.0.8:
resolution: {integrity: sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==}
dev: true
/@tsconfig/node12/1.0.9:
resolution: {integrity: sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==}
dev: true
/@tsconfig/node14/1.0.1:
resolution: {integrity: sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==}
dev: true
/@tsconfig/node16/1.0.2:
resolution: {integrity: sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==}
dev: true
/@types/babel__core/7.1.16:
resolution: {integrity: sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ==}
dependencies:
@@ -1855,6 +1883,10 @@ packages:
'@types/node': 16.11.6
dev: true
/@types/semver/7.3.9:
resolution: {integrity: sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==}
dev: true
/@types/stack-utils/2.0.1:
resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==}
dev: true
@@ -1998,7 +2030,7 @@ packages:
chalk: 2.4.2
convert-source-map: 1.8.0
extract-from-css: 0.4.4
jest: 27.3.1
jest: 27.3.1_ts-node@10.4.0
source-map: 0.5.6
ts-jest: 27.0.7_2c4ca6574207836d1023f54689cc81ac
tsconfig: 7.0.0
@@ -2059,6 +2091,11 @@ packages:
engines: {node: '>=0.4.0'}
dev: true
/acorn-walk/8.2.0:
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
engines: {node: '>=0.4.0'}
dev: true
/acorn/7.4.1:
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
engines: {node: '>=0.4.0'}
@@ -2145,6 +2182,10 @@ packages:
normalize-path: 3.0.0
picomatch: 2.3.0
/arg/4.1.3:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
dev: true
/argparse/1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
dependencies:
@@ -2177,21 +2218,6 @@ packages:
hasBin: true
dev: true
/autoprefixer/10.4.0:
resolution: {integrity: sha512-7FdJ1ONtwzV1G43GDD0kpVMn/qbiNqyOPMFTX5nRffI+7vgWoFEc6DcXOxHJxrWNDXrZh18eDsZjvZGUljSRGA==}
engines: {node: ^10 || ^12 || >=14}
hasBin: true
peerDependencies:
postcss: ^8.1.0
dependencies:
browserslist: 4.17.5
caniuse-lite: 1.0.30001278
fraction.js: 4.1.1
normalize-range: 0.1.2
picocolors: 1.0.0
postcss-value-parser: 4.1.0
dev: false
/babel-jest/27.3.1_@babel+core@7.16.0:
resolution: {integrity: sha512-SjIF8hh/ir0peae2D6S6ZKRhUy7q/DnpH7k/V6fT4Bgs/LXXUztOpX4G2tCgq8mLo5HA9mN6NmlFMeYtKmIsTQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
@@ -2358,18 +2384,6 @@ packages:
resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==}
dev: true
/browserslist/4.17.5:
resolution: {integrity: sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
caniuse-lite: 1.0.30001278
electron-to-chromium: 1.3.884
escalade: 3.1.1
node-releases: 2.0.1
picocolors: 1.0.0
dev: false
/browserslist/4.17.6:
resolution: {integrity: sha512-uPgz3vyRTlEiCv4ee9KlsKgo2V6qPk7Jsn0KAn2OBqbqKo3iNcPEC1Ti6J4dwnz+aIRfEEEuOzC9IBk8tXUomw==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
@@ -2471,6 +2485,7 @@ packages:
/caniuse-lite/1.0.30001278:
resolution: {integrity: sha512-mpF9KeH8u5cMoEmIic/cr7PNS+F5LWBk0t2ekGT60lFf0Wq+n9LspAj0g3P+o7DQhD3sUdlMln4YFAWhFYn9jg==}
dev: true
/chalk/2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
@@ -2688,6 +2703,10 @@ packages:
yaml: 1.10.2
dev: true
/create-require/1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
dev: true
/cross-spawn/6.0.5:
resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==}
engines: {node: '>=4.8'}
@@ -2868,6 +2887,11 @@ packages:
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
dev: true
/diff/4.0.2:
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
engines: {node: '>=0.3.1'}
dev: true
/dir-glob/3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
@@ -2903,10 +2927,6 @@ packages:
sigmund: 1.0.1
dev: true
/electron-to-chromium/1.3.884:
resolution: {integrity: sha512-kOaCAa+biA98PwH5BpCkeUeTL6mCeg8p3Q3OhqzPyqhu/5QUnWAN2wr/3IK8xMQxIV76kfoQpP+Bn/wij/jXrg==}
dev: false
/electron-to-chromium/1.3.890:
resolution: {integrity: sha512-VWlVXSkv0cA/OOehrEyqjUTHwV8YXCPTfPvbtoeU2aHR21vI4Ejh5aC4AxUwOmbLbBgb6Gd3URZahoCxtBqCYQ==}
dev: true
@@ -3141,6 +3161,7 @@ packages:
/escalade/3.1.1:
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
engines: {node: '>=6'}
dev: true
/escape-goat/2.1.1:
resolution: {integrity: sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==}
@@ -3348,10 +3369,6 @@ packages:
mime-types: 2.1.32
dev: true
/fraction.js/4.1.1:
resolution: {integrity: sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg==}
dev: false
/fs.realpath/1.0.0:
resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=}
dev: true
@@ -4059,7 +4076,7 @@ packages:
- supports-color
dev: true
/jest-cli/27.3.1:
/jest-cli/27.3.1_ts-node@10.4.0:
resolution: {integrity: sha512-WHnCqpfK+6EvT62me6WVs8NhtbjAS4/6vZJnk7/2+oOr50cwAzG4Wxt6RXX0hu6m1169ZGMlhYYUNeKBXCph/Q==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
hasBin: true
@@ -4069,14 +4086,14 @@ packages:
node-notifier:
optional: true
dependencies:
'@jest/core': 27.3.1
'@jest/core': 27.3.1_ts-node@10.4.0
'@jest/test-result': 27.3.1
'@jest/types': 27.2.5
chalk: 4.1.2
exit: 0.1.2
graceful-fs: 4.2.8
import-local: 3.0.3
jest-config: 27.3.1
jest-config: 27.3.1_ts-node@10.4.0
jest-util: 27.3.1
jest-validate: 27.3.1
prompts: 2.4.2
@@ -4089,7 +4106,7 @@ packages:
- utf-8-validate
dev: true
/jest-config/27.3.1:
/jest-config/27.3.1_ts-node@10.4.0:
resolution: {integrity: sha512-KY8xOIbIACZ/vdYCKSopL44I0xboxC751IX+DXL2+Wx6DKNycyEfV3rryC3BPm5Uq/BBqDoMrKuqLEUNJmMKKg==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
peerDependencies:
@@ -4119,6 +4136,7 @@ packages:
jest-validate: 27.3.1
micromatch: 4.0.4
pretty-format: 27.3.1
ts-node: 10.4.0_typescript@4.4.4
transitivePeerDependencies:
- bufferutil
- canvas
@@ -4479,7 +4497,7 @@ packages:
supports-color: 8.1.1
dev: true
/jest/27.3.1:
/jest/27.3.1_ts-node@10.4.0:
resolution: {integrity: sha512-U2AX0AgQGd5EzMsiZpYt8HyZ+nSVIh5ujQ9CPp9EQZJMjXIiSZpJNweZl0swatKRoqHWgGKM3zaSwm4Zaz87ng==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
hasBin: true
@@ -4489,9 +4507,9 @@ packages:
node-notifier:
optional: true
dependencies:
'@jest/core': 27.3.1
'@jest/core': 27.3.1_ts-node@10.4.0
import-local: 3.0.3
jest-cli: 27.3.1
jest-cli: 27.3.1_ts-node@10.4.0
transitivePeerDependencies:
- bufferutil
- canvas
@@ -4925,6 +4943,7 @@ packages:
/node-releases/2.0.1:
resolution: {integrity: sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==}
dev: true
/nopt/5.0.0:
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
@@ -4947,11 +4966,6 @@ packages:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
/normalize-range/0.1.2:
resolution: {integrity: sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=}
engines: {node: '>=0.10.0'}
dev: false
/normalize-url/4.5.1:
resolution: {integrity: sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==}
engines: {node: '>=8'}
@@ -5245,10 +5259,6 @@ packages:
semver-compare: 1.0.0
dev: true
/postcss-value-parser/4.1.0:
resolution: {integrity: sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==}
dev: false
/postcss/8.3.11:
resolution: {integrity: sha512-hCmlUAIlUiav8Xdqw3Io4LcpA1DOt7h3LSTAC4G6JGHFFaWzI6qvFt9oilvl8BmkbBRX1IhM90ZAmpk68zccQA==}
engines: {node: ^10 || ^12 || >=14}
@@ -5838,10 +5848,6 @@ packages:
escape-string-regexp: 2.0.0
dev: true
/store/2.0.12:
resolution: {integrity: sha1-jFNOKguDH3K3X8XxEZhXxE711ZM=}
dev: false
/strict-uri-encode/2.0.0:
resolution: {integrity: sha1-ucczDHBChi9rFC3CdLvMWGbONUY=}
engines: {node: '>=4'}
@@ -6059,7 +6065,7 @@ packages:
'@types/jest': 27.0.2
bs-logger: 0.2.6
fast-json-stable-stringify: 2.1.0
jest: 27.3.1
jest: 27.3.1_ts-node@10.4.0
jest-util: 27.3.1
json5: 2.2.0
lodash.memoize: 4.1.2
@@ -6069,6 +6075,35 @@ packages:
yargs-parser: 20.2.9
dev: true
/ts-node/10.4.0_typescript@4.4.4:
resolution: {integrity: sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==}
hasBin: true
peerDependencies:
'@swc/core': '>=1.2.50'
'@swc/wasm': '>=1.2.50'
'@types/node': '*'
typescript: '>=2.7'
peerDependenciesMeta:
'@swc/core':
optional: true
'@swc/wasm':
optional: true
dependencies:
'@cspotcode/source-map-support': 0.7.0
'@tsconfig/node10': 1.0.8
'@tsconfig/node12': 1.0.9
'@tsconfig/node14': 1.0.1
'@tsconfig/node16': 1.0.2
acorn: 8.5.0
acorn-walk: 8.2.0
arg: 4.1.3
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
typescript: 4.4.4
yn: 3.1.1
dev: true
/tsconfig/7.0.0:
resolution: {integrity: sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==}
dependencies:
@@ -6609,6 +6644,11 @@ packages:
yargs-parser: 20.2.9
dev: true
/yn/3.1.1:
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
engines: {node: '>=6'}
dev: true
/yocto-queue/0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}