Compare commits

..

3 Commits

31 changed files with 174 additions and 329 deletions

View File

@@ -1,4 +1,4 @@
FROM nginx:latest
FROM nginx:1.29.4-trixie
COPY public /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf.template

View File

@@ -19,7 +19,7 @@
"chart.js": "3.9.1",
"connect-history-api-fallback": "2.0.0",
"dotenv": "^16.0.1",
"express": "4.21.1",
"express": "4.18.1",
"vue": "3.2.37",
"vue-router": "4.1.3",
"vuex": "4.0.2"

View File

@@ -4,7 +4,7 @@ import type {
IRequestSubmitResponse
} from "./interfaces/IRequestResponse";
const { ELASTIC, ELASTIC_INDEX } = process.env;
const { ELASTIC, ELASTIC_INDEX, ELASTIC_APIKEY } = process.env;
const API_HOSTNAME = window.location.origin;
// - - - TMDB - - -
@@ -430,9 +430,13 @@ const unlinkPlexAccount = () => {
// - - - User graphs - - -
const fetchGraphData = (urlPath, days, chartType) => {
const fetchGraphData = async (
urlPath: string,
days: number,
chartType: string
) => {
const url = new URL(`/api/v1/user/${urlPath}`, API_HOSTNAME);
url.searchParams.append("days", days);
url.searchParams.append("days", String(days));
url.searchParams.append("y_axis", chartType);
return fetch(url.href).then(resp => {
@@ -447,7 +451,7 @@ const fetchGraphData = (urlPath, days, chartType) => {
// - - - Random emoji - - -
const getEmoji = () => {
const getEmoji = async () => {
const url = new URL("/api/v1/emoji", API_HOSTNAME);
return fetch(url.href)
@@ -468,33 +472,58 @@ const getEmoji = () => {
* @param {string} query
* @returns {object} List of movies and shows matching query
*/
const elasticSearchMoviesAndShows = (query, count = 22) => {
const elasticSearchMoviesAndShows = (query: string, count = 22) => {
const url = new URL(`${ELASTIC_INDEX}/_search`, ELASTIC);
const body = {
sort: [{ popularity: { order: "desc" } }, "_score"],
size: count,
query: {
bool: {
should: [
{
match_phrase_prefix: {
original_name: query
}
},
{
match_phrase_prefix: {
original_title: query
}
}
]
multi_match: {
query,
fields: ["name", "original_title", "original_name"],
type: "phrase_prefix",
tie_breaker: 0.3
}
},
size: count
suggest: {
text: query,
"person-suggest": {
prefix: query,
completion: {
field: "name.completion",
fuzzy: {
fuzziness: "AUTO"
}
}
},
"movie-suggest": {
prefix: query,
completion: {
field: "original_title.completion",
fuzzy: {
fuzziness: "AUTO"
}
}
},
"show-suggest": {
prefix: query,
completion: {
field: "original_name.completion",
fuzzy: {
fuzziness: "AUTO"
}
}
}
}
};
const options = {
method: "POST",
headers: { "Content-Type": "application/json" },
headers: {
Authorization: `ApiKey ${ELASTIC_APIKEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify(body)
};

View File

@@ -11,7 +11,6 @@
</template>
<script setup lang="ts">
import { defineProps } from "vue";
import CastListItem from "src/components/CastListItem.vue";
import type {
IMovie,

View File

@@ -9,7 +9,7 @@
</template>
<script setup lang="ts">
import { defineProps, computed } from "vue";
import { computed } from "vue";
import { useStore } from "vuex";
import type { ICast, ICrew, IMovie, IShow } from "../interfaces/IList";

View File

@@ -3,7 +3,7 @@
</template>
<script setup lang="ts">
import { ref, defineProps, onMounted, watch } from "vue";
import { ref, onMounted, watch } from "vue";
import {
Chart,
LineElement,

View File

@@ -23,7 +23,7 @@
</template>
<script setup lang="ts">
import { defineProps, computed } from "vue";
import { computed } from "vue";
interface Props {
title: string;

View File

@@ -17,7 +17,6 @@
</template>
<script setup lang="ts">
import { defineProps } from "vue";
import ResultsListItem from "@/components/ResultsListItem.vue";
import type { ListResults } from "../interfaces/IList";

View File

@@ -35,7 +35,7 @@
</template>
<script setup lang="ts">
import { ref, computed, defineProps, onMounted } from "vue";
import { ref, computed, onMounted } from "vue";
import { useStore } from "vuex";
import type { Ref } from "vue";
import type { IMovie, IShow, IPerson } from "../interfaces/IList";

View File

@@ -27,7 +27,7 @@
</template>
<script setup lang="ts">
import { defineProps, ref, computed, onMounted } from "vue";
import { ref, computed, onMounted } from "vue";
import PageHeader from "@/components/PageHeader.vue";
import ResultsList from "@/components/ResultsList.vue";
import SeasonedButton from "@/components/ui/SeasonedButton.vue";

View File

@@ -10,6 +10,7 @@
>
<IconMovie v-if="result.type == 'movie'" class="type-icon" />
<IconShow v-if="result.type == 'show'" class="type-icon" />
<IconPerson v-if="result.type == 'person'" class="type-icon" />
<span class="title">{{ result.title }}</span>
</li>
@@ -23,18 +24,25 @@
</transition>
</template>
<!--
Searches Elasticsearch for results based on changes to `query`.
-->
<script setup lang="ts">
import { ref, watch, defineProps } from "vue";
import { ref, watch } from "vue";
import { useStore } from "vuex";
import IconMovie from "@/icons/IconMovie.vue";
import IconShow from "@/icons/IconShow.vue";
import IconPerson from "@/icons/IconPerson.vue";
import type { Ref } from "vue";
import { elasticSearchMoviesAndShows } from "../../api";
import { MediaTypes } from "../../interfaces/IList";
import { Index } from "../../interfaces/IAutocompleteSearch";
import type {
IAutocompleteResult,
IAutocompleteSearchResults
IAutocompleteSearchResults,
Hit,
Option,
Source
} from "../../interfaces/IAutocompleteSearch";
interface Props {
@@ -48,6 +56,7 @@
}
const numberOfResults = 10;
let timeoutId = null;
const props = defineProps<Props>();
const emit = defineEmits<Emit>();
const store = useStore();
@@ -55,23 +64,9 @@
const searchResults: Ref<Array<IAutocompleteResult>> = ref([]);
const keyboardNavigationIndex: Ref<number> = ref(0);
watch(
() => props.query,
newQuery => {
if (newQuery?.length > 0)
fetchAutocompleteResults(); /* eslint-disable-line no-use-before-define */
}
);
function openPopup(result) {
if (!result.id || !result.type) return;
store.dispatch("popup/open", { ...result });
}
function removeDuplicates(_searchResults) {
function removeDuplicates(_searchResults: Array<IAutocompleteResult>) {
const filteredResults = [];
_searchResults.forEach(result => {
_searchResults.forEach((result: IAutocompleteResult) => {
if (result === undefined) return;
const numberOfDuplicates = filteredResults.filter(
filterItem => filterItem.id === result.id
@@ -86,34 +81,43 @@
return filteredResults;
}
function elasticIndexToMediaType(index: Index): MediaTypes {
if (index === Index.Movies) return MediaTypes.Movie;
if (index === Index.Shows) return MediaTypes.Show;
function convertMediaType(type: string | null): MediaTypes | null {
if (type === "movie") return MediaTypes.Movie;
if (type === "tv_series") return MediaTypes.Show;
if (type === "person") return MediaTypes.Person;
return null;
}
function parseElasticResponse(elasticResponse: IAutocompleteSearchResults) {
const data = elasticResponse.hits.hits;
const elasticResults = elasticResponse.hits.hits;
const suggestResults = elasticResponse.suggest["movie-suggest"][0].options;
let data: Array<Source> = elasticResults.map((el: Hit) => el._source);
data = data.concat(suggestResults.map((el: Option) => el._source));
// data = data.concat(elasticResponse['suggest']['person-suggest'][0]['options'])
// data = data.concat(elasticResponse['suggest']['show-suggest'][0]['options'])
data = data.sort((a, b) => (a.popularity < b.popularity ? 1 : -1));
const results: Array<IAutocompleteResult> = [];
data.forEach(item => {
if (!Object.values(Index).includes(item._index)) {
return;
}
results.push({
title: item._source?.original_name || item._source.original_title,
id: item._source.id,
adult: item._source.adult,
type: elasticIndexToMediaType(item._index)
title: item?.original_name || item?.original_title || item?.name,
id: item.id,
adult: item.adult,
type: convertMediaType(item?.type)
});
});
return removeDuplicates(results).map((el, index) => {
return { ...el, index };
});
return removeDuplicates(results)
.map((el, index) => {
return { ...el, index };
})
.slice(0, 10);
}
function fetchAutocompleteResults() {
@@ -123,11 +127,34 @@
elasticSearchMoviesAndShows(props.query, numberOfResults)
.then(elasticResponse => parseElasticResponse(elasticResponse))
.then(_searchResults => {
console.log(_searchResults);
emit("update:results", _searchResults);
searchResults.value = _searchResults;
});
}
const debounce = (callback: () => void, wait: number) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
callback();
}, wait);
};
watch(
() => props.query,
newQuery => {
if (newQuery?.length > 0) {
debounce(fetchAutocompleteResults, 150);
}
}
);
function openPopup(result: IAutocompleteResult) {
if (!result.id || !result.type) return;
store.dispatch("popup/open", { ...result });
}
// on load functions
fetchAutocompleteResults();
// end on load functions

View File

@@ -16,7 +16,7 @@
<script setup lang="ts">
import { useStore } from "vuex";
import { computed, defineProps } from "vue";
import { computed } from "vue";
import type INavigationIcon from "../../interfaces/INavigationIcon";
interface Props {

View File

@@ -42,6 +42,18 @@
</div>
</template>
<!-- Handles constructing markup and state for dropdown.
Markup:
Consist of: search icon, input & close button.
State:
State is passing input variable `query` to dropdown and carrying state
of selected dropdown element as variable `index`. This is because
index is manipulated based on arrow key events from same input as
the `query`.
-->
<script setup lang="ts">
import { ref, computed } from "vue";
import { useStore } from "vuex";
@@ -51,6 +63,7 @@
import IconClose from "@/icons/IconClose.vue";
import type { Ref } from "vue";
import type { MediaTypes } from "../../interfaces/IList";
import { IAutocompleteResult } from "../../interfaces/IAutocompleteSearch";
interface ISearchResult {
title: string;
@@ -66,7 +79,7 @@
const query: Ref<string> = ref(null);
const disabled: Ref<boolean> = ref(false);
const dropdownIndex: Ref<number> = ref(-1);
const dropdownResults: Ref<ISearchResult[]> = ref([]);
const dropdownResults: Ref<IAutocompleteResult[]> = ref([]);
const inputIsActive: Ref<boolean> = ref(false);
const inputElement: Ref<HTMLInputElement> = ref(null);
@@ -85,8 +98,13 @@
query.value = decodeURIComponent(params.get("query"));
}
const { ELASTIC } = process.env;
if (ELASTIC === undefined || ELASTIC === "") {
const { ELASTIC, ELASTIC_APIKEY } = process.env;
if (
ELASTIC === undefined ||
ELASTIC === "" ||
ELASTIC_APIKEY === undefined ||
ELASTIC_APIKEY === ""
) {
disabled.value = true;
}
@@ -145,6 +163,7 @@
function handleSubmit() {
if (!query.value || query.value.length === 0) return;
// if index is set, navigation has happened. Open popup else search
if (dropdownIndex.value >= 0) {
const resultItem = dropdownResults.value[dropdownIndex.value];

View File

@@ -10,8 +10,6 @@
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from "vue";
interface Props {
active?: boolean;
disabled?: boolean;

View File

@@ -14,7 +14,7 @@
</template>
<script setup lang="ts">
import { ref, defineProps, onMounted } from "vue";
import { ref, onMounted } from "vue";
import type { Ref } from "vue";
import IconArrowDown from "../../icons/IconArrowDown.vue";

View File

@@ -8,8 +8,6 @@
</template>
<script setup lang="ts">
import { defineProps } from "vue";
interface Props {
title: string;
detail?: string | number;

View File

@@ -165,7 +165,7 @@
</template>
<script setup lang="ts">
import { ref, computed, defineProps, onMounted } from "vue";
import { ref, computed, onMounted } from "vue";
import { useStore } from "vuex";
// import img from "@/directives/v-image";

View File

@@ -70,7 +70,7 @@
</template>
<script setup lang="ts">
import { ref, computed, defineProps } from "vue";
import { ref, computed } from "vue";
import CastList from "@/components/CastList.vue";
import Detail from "@/components/popup/Detail.vue";
import Description from "@/components/popup/Description.vue";

View File

@@ -43,7 +43,7 @@
</template>
<script setup lang="ts">
import { ref, computed, defineEmits } from "vue";
import { ref, computed } from "vue";
import { useStore } from "vuex";
import seasonedInput from "@/components/ui/SeasonedInput.vue";
import SeasonedButton from "@/components/ui/SeasonedButton.vue";

View File

@@ -20,7 +20,7 @@
</template>
<script setup lang="ts">
import { ref, watch, inject, defineProps } from "vue";
import { ref, watch, inject } from "vue";
import { useStore } from "vuex";
import Loader from "@/components/ui/Loader.vue";
import TorrentTable from "@/components/torrent/TorrentTable.vue";

View File

@@ -52,7 +52,7 @@
</template>
<script setup lang="ts">
import { ref, defineProps, defineEmits } from "vue";
import { ref } from "vue";
import IconMagnet from "@/icons/IconMagnet.vue";
import type { Ref } from "vue";
import { sortableSize } from "../../utils";

View File

@@ -25,7 +25,7 @@
</template>
<script setup lang="ts">
import { ref, defineProps } from "vue";
import { ref } from "vue";
import { useRouter } from "vue-router";
import TorrentSearchResults from "@/components/torrent/TorrentSearchResults.vue";
import SeasonedButton from "@/components/ui/SeasonedButton.vue";

View File

@@ -12,7 +12,6 @@
--></template>
<script setup lang="ts">
import { defineProps } from "vue";
import LoaderHeightType from "../../interfaces/ILoader";
interface Props {

View File

@@ -10,8 +10,6 @@
</template>
<script setup lang="ts">
import { defineProps } from "vue";
interface Props {
count?: number;
lineClass?: string;

View File

@@ -9,8 +9,6 @@
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from "vue";
interface Props {
active?: boolean;
fullWidth?: boolean;

View File

@@ -26,7 +26,7 @@
</template>
<script setup lang="ts">
import { ref, computed, defineProps, defineEmits } from "vue";
import { ref, computed } from "vue";
import IconKey from "@/icons/IconKey.vue";
import IconEmail from "@/icons/IconEmail.vue";
import IconBinoculars from "@/icons/IconBinoculars.vue";

View File

@@ -22,7 +22,6 @@
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from "vue";
import type {
ErrorMessageTypes,
IErrorMessage

View File

@@ -13,8 +13,6 @@
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from "vue";
interface Props {
options: string[];
selected?: string;

View File

@@ -13,6 +13,7 @@ export interface IAutocompleteSearchResults {
timed_out: boolean;
_shards: Shards;
hits: Hits;
suggest: Suggest;
}
export interface Shards {
@@ -37,6 +38,27 @@ export interface Hit {
sort: number[];
}
export interface Suggest {
"movie-suggest": SuggestOptions[];
"person-suggest": SuggestOptions[];
"show-suggest": SuggestOptions[];
}
export interface SuggestOptions {
text: string;
offset: number;
length: number;
options: Option[];
}
export interface Option {
text: string;
_index: string;
_id: string;
_score: number;
_source: Source;
}
export enum Index {
Movies = "movies",
Shows = "shows"
@@ -57,6 +79,8 @@ export interface Source {
agent: Agent;
original_title: string;
original_name?: string;
name?: string;
type?: MediaTypes;
}
export interface Agent {

View File

@@ -28,7 +28,7 @@
</template>
<script setup lang="ts">
import { ref, defineProps, onMounted } from "vue";
import { ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import type { Ref } from "vue";

242
yarn.lock
View File

@@ -2775,24 +2775,6 @@ body-parser@1.20.0, body-parser@^1.19.0:
type-is "~1.6.18"
unpipe "1.0.0"
body-parser@1.20.3:
version "1.20.3"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6"
integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==
dependencies:
bytes "3.1.2"
content-type "~1.0.5"
debug "2.6.9"
depd "2.0.0"
destroy "1.2.0"
http-errors "2.0.0"
iconv-lite "0.4.24"
on-finished "2.4.1"
qs "6.13.0"
raw-body "2.5.2"
type-is "~1.6.18"
unpipe "1.0.0"
body@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/body/-/body-5.1.0.tgz#e4ba0ce410a46936323367609ecb4e6553125069"
@@ -2994,17 +2976,6 @@ call-bind@^1.0.0, call-bind@^1.0.2:
function-bind "^1.1.1"
get-intrinsic "^1.0.2"
call-bind@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9"
integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==
dependencies:
es-define-property "^1.0.0"
es-errors "^1.3.0"
function-bind "^1.1.2"
get-intrinsic "^1.2.4"
set-function-length "^1.2.1"
callsites@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
@@ -3463,11 +3434,6 @@ content-type@~1.0.4:
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
content-type@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
continuable-cache@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/continuable-cache/-/continuable-cache-0.3.1.tgz#bd727a7faed77e71ff3985ac93351a912733ad0f"
@@ -3653,11 +3619,6 @@ cookie@0.5.0:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
cookie@0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9"
integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==
copy-descriptor@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
@@ -4001,15 +3962,6 @@ defaults@^1.0.3:
dependencies:
clone "^1.0.2"
define-data-property@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
dependencies:
es-define-property "^1.0.0"
es-errors "^1.3.0"
gopd "^1.0.1"
define-lazy-prop@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
@@ -4365,11 +4317,6 @@ encodeurl@~1.0.2:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
encodeurl@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
@@ -4454,18 +4401,6 @@ es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19
string.prototype.trimstart "^1.0.5"
unbox-primitive "^1.0.2"
es-define-property@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==
dependencies:
get-intrinsic "^1.2.4"
es-errors@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
es-module-lexer@^0.9.0:
version "0.9.3"
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19"
@@ -4815,44 +4750,7 @@ express-history-api-fallback@^2.2.1:
resolved "https://registry.yarnpkg.com/express-history-api-fallback/-/express-history-api-fallback-2.2.1.tgz#3a2ad27f7bebc90fc533d110d7c6d83097bcd057"
integrity sha512-swxwm3aP8vrOOvlzOdZvHlSZtJGwHKaY94J6AkrAgCTmcbko3IRwbkhLv2wKV1WeZhjxX58aLMpP3atDBnKuZg==
express@4.21.1:
version "4.21.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.21.1.tgz#9dae5dda832f16b4eec941a4e44aa89ec481b281"
integrity sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==
dependencies:
accepts "~1.3.8"
array-flatten "1.1.1"
body-parser "1.20.3"
content-disposition "0.5.4"
content-type "~1.0.4"
cookie "0.7.1"
cookie-signature "1.0.6"
debug "2.6.9"
depd "2.0.0"
encodeurl "~2.0.0"
escape-html "~1.0.3"
etag "~1.8.1"
finalhandler "1.3.1"
fresh "0.5.2"
http-errors "2.0.0"
merge-descriptors "1.0.3"
methods "~1.1.2"
on-finished "2.4.1"
parseurl "~1.3.3"
path-to-regexp "0.1.10"
proxy-addr "~2.0.7"
qs "6.13.0"
range-parser "~1.2.1"
safe-buffer "5.2.1"
send "0.19.0"
serve-static "1.16.2"
setprototypeof "1.2.0"
statuses "2.0.1"
type-is "~1.6.18"
utils-merge "1.0.1"
vary "~1.1.2"
express@^4.17.1, express@^4.17.3:
express@4.18.1, express@^4.17.1, express@^4.17.3:
version "4.18.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf"
integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==
@@ -5121,19 +5019,6 @@ finalhandler@1.2.0:
statuses "2.0.1"
unpipe "~1.0.0"
finalhandler@1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019"
integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==
dependencies:
debug "2.6.9"
encodeurl "~2.0.0"
escape-html "~1.0.3"
on-finished "2.4.1"
parseurl "~1.3.3"
statuses "2.0.1"
unpipe "~1.0.0"
find-cache-dir@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
@@ -5314,11 +5199,6 @@ function-bind@^1.1.1:
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
function.prototype.name@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
@@ -5358,17 +5238,6 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
has "^1.0.3"
has-symbols "^1.0.3"
get-intrinsic@^1.1.3, get-intrinsic@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==
dependencies:
es-errors "^1.3.0"
function-bind "^1.1.2"
has-proto "^1.0.1"
has-symbols "^1.0.3"
hasown "^2.0.0"
get-pkg-repo@^4.0.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz#75973e1c8050c73f48190c52047c4cee3acbf385"
@@ -5598,13 +5467,6 @@ globby@^11.0.2, globby@^11.0.3, globby@^11.1.0:
merge2 "^1.4.1"
slash "^3.0.0"
gopd@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
dependencies:
get-intrinsic "^1.1.3"
got@^8.3.1:
version "8.3.2"
resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937"
@@ -5718,18 +5580,6 @@ has-property-descriptors@^1.0.0:
dependencies:
get-intrinsic "^1.1.1"
has-property-descriptors@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
dependencies:
es-define-property "^1.0.0"
has-proto@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd"
integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==
has-symbol-support-x@^1.4.1:
version "1.4.2"
resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455"
@@ -5802,13 +5652,6 @@ hash-sum@^2.0.0:
resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-2.0.0.tgz#81d01bb5de8ea4a214ad5d6ead1b523460b0b45a"
integrity sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==
hasown@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
dependencies:
function-bind "^1.1.2"
hast-util-is-element@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz#3b3ed5159a2707c6137b48637fbfe068e175a425"
@@ -7239,11 +7082,6 @@ merge-descriptors@1.0.1:
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
merge-descriptors@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5"
integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==
merge-source-map@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646"
@@ -7726,11 +7564,6 @@ object-inspect@^1.12.0, object-inspect@^1.9.0:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
object-inspect@^1.13.1:
version "1.13.2"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff"
integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==
object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
@@ -8134,11 +7967,6 @@ path-root@^0.1.1:
dependencies:
path-root-regex "^0.1.0"
path-to-regexp@0.1.10:
version "0.1.10"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b"
integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==
path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
@@ -8672,13 +8500,6 @@ qs@6.10.3:
dependencies:
side-channel "^1.0.4"
qs@6.13.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==
dependencies:
side-channel "^1.0.6"
qs@^6.4.0, qs@^6.9.4:
version "6.11.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
@@ -8737,16 +8558,6 @@ raw-body@2.5.1:
iconv-lite "0.4.24"
unpipe "1.0.0"
raw-body@2.5.2:
version "2.5.2"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a"
integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==
dependencies:
bytes "3.1.2"
http-errors "2.0.0"
iconv-lite "0.4.24"
unpipe "1.0.0"
raw-body@~1.1.0:
version "1.1.7"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-1.1.7.tgz#1d027c2bfa116acc6623bca8f00016572a87d425"
@@ -9352,25 +9163,6 @@ send@0.18.0:
range-parser "~1.2.1"
statuses "2.0.1"
send@0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8"
integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==
dependencies:
debug "2.6.9"
depd "2.0.0"
destroy "1.2.0"
encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
fresh "0.5.2"
http-errors "2.0.0"
mime "1.6.0"
ms "2.1.3"
on-finished "2.4.1"
range-parser "~1.2.1"
statuses "2.0.1"
serialize-javascript@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8"
@@ -9401,33 +9193,11 @@ serve-static@1.15.0:
parseurl "~1.3.3"
send "0.18.0"
serve-static@1.16.2:
version "1.16.2"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296"
integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==
dependencies:
encodeurl "~2.0.0"
escape-html "~1.0.3"
parseurl "~1.3.3"
send "0.19.0"
set-blocking@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
set-function-length@^1.2.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==
dependencies:
define-data-property "^1.1.4"
es-errors "^1.3.0"
function-bind "^1.1.2"
get-intrinsic "^1.2.4"
gopd "^1.0.1"
has-property-descriptors "^1.0.2"
set-value@^2.0.0, set-value@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
@@ -9513,16 +9283,6 @@ side-channel@^1.0.4:
get-intrinsic "^1.0.2"
object-inspect "^1.9.0"
side-channel@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2"
integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==
dependencies:
call-bind "^1.0.7"
es-errors "^1.3.0"
get-intrinsic "^1.2.4"
object-inspect "^1.13.1"
signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
version "3.0.7"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"