Compare commits
9 Commits
main
...
cal/dev-46
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
daab8d9235 | ||
|
|
3203681e3b | ||
|
|
e5cec38ac5 | ||
|
|
3961876cb4 | ||
|
|
7eee57eca3 | ||
|
|
6482d5b465 | ||
|
|
c48a229900 | ||
|
|
39a37096dd | ||
|
|
ab2b41a74d |
@ -41,10 +41,12 @@
|
||||
"@modrinth/ui": "workspace:*",
|
||||
"@modrinth/utils": "workspace:*",
|
||||
"@pinia/nuxt": "^0.5.1",
|
||||
"@types/three": "^0.172.0",
|
||||
"@vintl/vintl": "^4.4.1",
|
||||
"@vueuse/core": "^11.1.0",
|
||||
"ace-builds": "^1.36.2",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"cronstrue": "^2.61.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"dompurify": "^3.1.7",
|
||||
"floating-vue": "^5.2.2",
|
||||
@ -59,7 +61,6 @@
|
||||
"qrcode.vue": "^3.4.0",
|
||||
"semver": "^7.5.4",
|
||||
"three": "^0.172.0",
|
||||
"@types/three": "^0.172.0",
|
||||
"vue-multiselect": "3.0.0-alpha.2",
|
||||
"vue-typed-virtual-list": "^1.0.10",
|
||||
"vue3-ace-editor": "^2.2.4",
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<NuxtLink
|
||||
:to="link.href"
|
||||
class="flex items-center gap-2 rounded-xl p-2 hover:bg-button-bg"
|
||||
:class="{ 'bg-button-bg text-contrast': route.path === link.href }"
|
||||
:class="{ 'bg-button-bg text-contrast': isLinkActive(link) }"
|
||||
>
|
||||
<div class="flex items-center gap-2 font-bold">
|
||||
<component :is="link.icon" class="size-6" />
|
||||
@ -39,13 +39,33 @@ import { ModrinthServer } from "~/composables/servers/modrinth-servers.ts";
|
||||
|
||||
const emit = defineEmits(["reinstall"]);
|
||||
|
||||
defineProps<{
|
||||
navLinks: { label: string; href: string; icon: Component; external?: boolean }[];
|
||||
const props = defineProps<{
|
||||
navLinks: {
|
||||
label: string;
|
||||
href: string;
|
||||
icon: Component;
|
||||
external?: boolean;
|
||||
matches?: RegExp[];
|
||||
}[];
|
||||
route: RouteLocationNormalized;
|
||||
server: ModrinthServer;
|
||||
backupInProgress?: BackupInProgressReason;
|
||||
}>();
|
||||
|
||||
const isLinkActive = (link: (typeof props.navLinks)[0]) => {
|
||||
if (props.route.path === link.href) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (link.matches && link.matches.length > 0) {
|
||||
return link.matches.some((regex: RegExp) => {
|
||||
return regex.test(props.route.path);
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const onReinstall = (...args: any[]) => {
|
||||
emit("reinstall", ...args);
|
||||
};
|
||||
|
||||
@ -0,0 +1,531 @@
|
||||
<template>
|
||||
<NewModal
|
||||
ref="modal"
|
||||
:header="isNew ? 'New scheduled task' : 'Editing scheduled task'"
|
||||
@hide="onModalHide"
|
||||
>
|
||||
<div class="modal-content flex flex-col gap-2">
|
||||
<div v-if="error" class="text-sm text-brand-red">
|
||||
{{ error }}
|
||||
</div>
|
||||
|
||||
<div class="flex max-w-md flex-col gap-2">
|
||||
<label for="title">
|
||||
<span class="text-lg font-bold text-contrast">
|
||||
Title <span class="text-brand-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
id="title"
|
||||
v-model="task.title"
|
||||
type="text"
|
||||
maxlength="64"
|
||||
placeholder="Enter task title..."
|
||||
autocomplete="off"
|
||||
class="input input-bordered"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<label><span class="text-lg font-bold text-contrast">Schedule Type</span></label>
|
||||
<RadioButtons v-model="scheduleType" :items="['daily', 'custom']" class="mb-2">
|
||||
<template #default="{ item }">
|
||||
<span class="flex items-center gap-2">
|
||||
<ClockIcon v-if="item === 'daily'" class="size-5" />
|
||||
<CodeIcon v-else class="size-5" />
|
||||
<span>{{
|
||||
item === "daily" ? "Every X day(s) at specific time" : "Custom cron expression"
|
||||
}}</span>
|
||||
</span>
|
||||
</template>
|
||||
</RadioButtons>
|
||||
</div>
|
||||
|
||||
<div class="card flex h-[140px] items-center overflow-hidden rounded-lg !bg-bg">
|
||||
<Transition
|
||||
name="schedule-content"
|
||||
mode="out-in"
|
||||
enter-active-class="transition-all duration-300 ease-in-out"
|
||||
leave-active-class="transition-all duration-300 ease-in-out"
|
||||
enter-from-class="opacity-0"
|
||||
enter-to-class="opacity-100"
|
||||
leave-from-class="opacity-100"
|
||||
leave-to-class="opacity-0"
|
||||
>
|
||||
<div v-if="scheduleType === 'daily'" key="daily" class="flex w-full flex-col gap-2">
|
||||
<div class="flex w-full gap-8">
|
||||
<div class="flex flex-col gap-2">
|
||||
<label for="dayInterval" class="text-md font-medium">Every X day(s)</label>
|
||||
<div class="flex items-center gap-2">
|
||||
<input
|
||||
id="dayInterval"
|
||||
v-model="dayInterval"
|
||||
type="text"
|
||||
inputmode="numeric"
|
||||
maxlength="3"
|
||||
class="input input-bordered w-20"
|
||||
placeholder="1"
|
||||
@input="onDayIntervalInput"
|
||||
/>
|
||||
<span class="text-muted-foreground text-sm">day(s)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<label class="text-md font-medium">At time</label>
|
||||
<TimePicker v-model="selectedTime" use-utc-values placeholder="Select time" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-xs">
|
||||
{{ humanReadableDescription }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else key="custom" class="flex w-full flex-col gap-2">
|
||||
<label for="customCron" class="text-md font-medium"
|
||||
>Cron Expression
|
||||
<nuxt-link
|
||||
v-tooltip="
|
||||
`Click to read more about what cron expressions are, and how to create them.`
|
||||
"
|
||||
class="align-middle text-link"
|
||||
target="_blank"
|
||||
to="https://www.geeksforgeeks.org/writing-cron-expressions-for-scheduling-tasks/"
|
||||
><UnknownIcon class="size-4" />
|
||||
</nuxt-link>
|
||||
</label>
|
||||
<input
|
||||
id="customCron"
|
||||
v-model="customCron"
|
||||
type="text"
|
||||
class="input input-bordered font-mono"
|
||||
placeholder="0 0 9 * * *"
|
||||
/>
|
||||
<div v-if="!isValidCron" class="text-xs text-brand-red">
|
||||
Invalid cron format. Please use 6 space-separated values (e.g.,
|
||||
<code>second minute hour day month day-of-week</code>).
|
||||
</div>
|
||||
<div v-else class="text-xs">
|
||||
{{ humanReadableDescription }}
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
<div class="flex max-w-md flex-col gap-2">
|
||||
<label for="action_kind"><span class="text-lg font-bold text-contrast">Action</span></label>
|
||||
<RadioButtons v-model="task.action_kind" :items="actionKinds" class="mb-2">
|
||||
<template #default="{ item }">
|
||||
<span>{{ item === "restart" ? "Restart server" : "Run game command" }}</span>
|
||||
</template>
|
||||
</RadioButtons>
|
||||
</div>
|
||||
|
||||
<Transition
|
||||
name="command-section"
|
||||
enter-active-class="transition-all duration-300 ease-in-out"
|
||||
leave-active-class="transition-all duration-300 ease-in-out"
|
||||
enter-from-class="opacity-0 max-h-0 overflow-hidden"
|
||||
enter-to-class="opacity-100 max-h-96 overflow-visible"
|
||||
leave-from-class="opacity-100 max-h-96 overflow-visible"
|
||||
leave-to-class="opacity-0 max-h-0 overflow-hidden"
|
||||
>
|
||||
<div v-if="task.action_kind === 'game-command'" class="flex max-w-lg flex-col gap-4">
|
||||
<label for="command" class="flex flex-col gap-2"
|
||||
><span class="text-lg font-bold text-contrast">
|
||||
Command <span class="text-brand-red">*</span>
|
||||
</span>
|
||||
<span
|
||||
>The command that will be ran when the task is executed. If the command is invalid
|
||||
nothing will happen.</span
|
||||
></label
|
||||
>
|
||||
<div class="max-w-md">
|
||||
<input
|
||||
id="command"
|
||||
v-model="commandValue"
|
||||
type="text"
|
||||
maxlength="256"
|
||||
placeholder="Enter command to run..."
|
||||
class="input input-bordered"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
|
||||
<div class="flex max-w-lg flex-col gap-4">
|
||||
<label for="warn_msg" class="flex flex-col gap-2"
|
||||
><span class="text-lg font-bold text-contrast">
|
||||
Warning Command
|
||||
<span
|
||||
v-if="task.warn_intervals && task.warn_intervals.length > 0"
|
||||
class="text-brand-red"
|
||||
>*</span
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
>You can use <code>{}</code> to insert the time until the task is executed. If the
|
||||
command is invalid nothing will happen.</span
|
||||
></label
|
||||
>
|
||||
<div class="max-w-md">
|
||||
<input
|
||||
id="warn_msg"
|
||||
v-model="task.warn_msg"
|
||||
type="text"
|
||||
maxlength="128"
|
||||
:placeholder="`/tellraw @a \u0022Restarting in {}!\u0022`"
|
||||
class="input input-bordered max-w-md"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex max-w-lg flex-col gap-4">
|
||||
<label for="warn_msg" class="flex flex-col gap-2"
|
||||
><span class="text-lg font-bold text-contrast">Warning Intervals</span>
|
||||
<span
|
||||
>When, at the time before the scheduled task is executed, should the warning command be
|
||||
executed?</span
|
||||
></label
|
||||
>
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
<Chips
|
||||
v-model="task.warn_intervals"
|
||||
:items="[5, 15, 30, 60, 120, 300, 600]"
|
||||
multi
|
||||
:never-empty="false"
|
||||
:format-label="formatWarningIntervalLabel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-2 flex max-w-md gap-2">
|
||||
<ButtonStyled color="brand">
|
||||
<button :disabled="!canSave" @click="saveTask">
|
||||
<SaveIcon />
|
||||
Save
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled>
|
||||
<button :disabled="loading" @click="closeModal">
|
||||
<XIcon />
|
||||
Cancel
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</div>
|
||||
</NewModal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Schedule, ServerSchedule, ActionKind } from "@modrinth/utils";
|
||||
import { ref, computed, watch } from "vue";
|
||||
import { RadioButtons, TimePicker, Chips, ButtonStyled, NewModal } from "@modrinth/ui";
|
||||
import { ClockIcon, CodeIcon, SaveIcon, XIcon, UnknownIcon } from "@modrinth/assets";
|
||||
import { toString as cronToString } from "cronstrue";
|
||||
import { ModrinthServer } from "~/composables/servers/modrinth-servers.ts";
|
||||
|
||||
const props = defineProps<{ server: ModrinthServer }>();
|
||||
|
||||
const modal = ref<InstanceType<typeof NewModal>>();
|
||||
const loading = ref(false);
|
||||
const error = ref<string | null>(null);
|
||||
const task = ref<Partial<ServerSchedule | Schedule>>({});
|
||||
const isNew = ref(true);
|
||||
const originalTaskId = ref<number | null>(null);
|
||||
|
||||
const scheduleType = ref<"daily" | "custom">("daily");
|
||||
const dayInterval = ref("1");
|
||||
const selectedTime = ref({ hour: "9", minute: "0" });
|
||||
const customCron = ref("0 0 9 * * *");
|
||||
const actionKinds: ActionKind[] = ["restart", "game-command"];
|
||||
|
||||
const commandValue = computed({
|
||||
get() {
|
||||
return task.value.options && "command" in task.value.options ? task.value.options.command : "";
|
||||
},
|
||||
set(val: string) {
|
||||
if (task.value.options && "command" in task.value.options) {
|
||||
task.value.options.command = val;
|
||||
} else if (task.value.action_kind === "game-command") {
|
||||
task.value.options = { command: val };
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const cronString = computed(() => {
|
||||
if (scheduleType.value === "custom") {
|
||||
return customCron.value.trim();
|
||||
}
|
||||
const minute = selectedTime.value.minute === "" ? "0" : selectedTime.value.minute;
|
||||
const hour = selectedTime.value.hour === "" ? "0" : selectedTime.value.hour;
|
||||
const days = dayInterval.value === "" || Number(dayInterval.value) < 1 ? "1" : dayInterval.value;
|
||||
if (days === "1") {
|
||||
return `0 ${minute} ${hour} * * *`;
|
||||
} else {
|
||||
return `0 ${minute} ${hour} */${days} * *`;
|
||||
}
|
||||
});
|
||||
|
||||
const CRON_REGEX =
|
||||
/^\s*([0-9*/,-]+)\s+([0-9*/,-]+)\s+([0-9*/,-]+)\s+([0-9*/,-]+)\s+([0-9*/,-]+)\s+([0-9*/,-]+)\s*$/;
|
||||
|
||||
const isValidCron = computed(() => {
|
||||
const cronToTest = scheduleType.value === "custom" ? customCron.value.trim() : cronString.value;
|
||||
|
||||
if (!CRON_REGEX.test(cronToTest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (scheduleType.value === "custom") {
|
||||
try {
|
||||
const parts = cronToTest.split(/\s+/);
|
||||
if (parts.length === 6) {
|
||||
cronToString(parts.slice(1).join(" "));
|
||||
}
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
const isValidGameCommand = computed(() => {
|
||||
if (task.value.action_kind === "game-command") {
|
||||
return commandValue.value && commandValue.value.trim().length > 0;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
const isValidWarningCommand = computed(() => {
|
||||
if (task.value.warn_intervals && task.value.warn_intervals.length > 0) {
|
||||
return task.value.warn_msg && task.value.warn_msg.trim().length > 0;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
const canSave = computed(() => {
|
||||
return (
|
||||
!loading.value &&
|
||||
task.value.title &&
|
||||
task.value.title.trim().length > 0 &&
|
||||
isValidCron.value &&
|
||||
isValidGameCommand.value &&
|
||||
isValidWarningCommand.value
|
||||
);
|
||||
});
|
||||
|
||||
const humanReadableDescription = computed<string | undefined>(() => {
|
||||
if (!isValidCron.value && scheduleType.value === "custom") return undefined;
|
||||
if (scheduleType.value === "custom") {
|
||||
try {
|
||||
const parts = customCron.value.trim().split(/\s+/);
|
||||
if (parts.length === 6) {
|
||||
return cronToString(parts.slice(1).join(" "));
|
||||
}
|
||||
return "Invalid cron expression";
|
||||
} catch {
|
||||
return "Invalid cron expression";
|
||||
}
|
||||
}
|
||||
const minute = selectedTime.value.minute === "" ? "0" : selectedTime.value.minute;
|
||||
const hour = selectedTime.value.hour === "" ? "0" : selectedTime.value.hour;
|
||||
const daysNum = Number(dayInterval.value || "1");
|
||||
const timeStr = `${hour.padStart(2, "0")}:${minute.padStart(2, "0")}`;
|
||||
if (daysNum <= 1) {
|
||||
return `Every day at ${timeStr}`;
|
||||
} else {
|
||||
return `Every ${daysNum} days at ${timeStr}`;
|
||||
}
|
||||
});
|
||||
|
||||
function formatWarningIntervalLabel(seconds: number): string {
|
||||
if (seconds < 60) {
|
||||
return `${seconds}s`;
|
||||
} else {
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
return `${minutes}m`;
|
||||
}
|
||||
}
|
||||
|
||||
function onDayIntervalInput(event: Event) {
|
||||
const input = event.target as HTMLInputElement;
|
||||
let value = input.value.replace(/\D/g, "");
|
||||
|
||||
if (value === "") {
|
||||
dayInterval.value = "";
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.length > 1 && value.startsWith("0")) {
|
||||
value = value.replace(/^0+/, "");
|
||||
}
|
||||
|
||||
const num = parseInt(value);
|
||||
|
||||
if (num < 1) {
|
||||
dayInterval.value = "1";
|
||||
} else if (num > 365) {
|
||||
dayInterval.value = "365";
|
||||
} else {
|
||||
dayInterval.value = String(num);
|
||||
}
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
task.value = {
|
||||
title: "",
|
||||
action_kind: "restart",
|
||||
options: {},
|
||||
enabled: true,
|
||||
warn_msg: '/tellraw @a "Restarting in {}!"',
|
||||
warn_intervals: [],
|
||||
};
|
||||
scheduleType.value = "daily";
|
||||
dayInterval.value = "1";
|
||||
selectedTime.value = { hour: "9", minute: "0" };
|
||||
customCron.value = "0 0 9 * * *";
|
||||
isNew.value = true;
|
||||
originalTaskId.value = null;
|
||||
error.value = null;
|
||||
if (isValidCron.value) {
|
||||
task.value.every = cronString.value;
|
||||
}
|
||||
}
|
||||
|
||||
function loadTaskData(taskData: ServerSchedule | Schedule) {
|
||||
task.value = { ...taskData };
|
||||
isNew.value = false;
|
||||
originalTaskId.value = "id" in taskData ? taskData.id : null;
|
||||
|
||||
if (task.value.every && typeof task.value.every === "string") {
|
||||
const parts = task.value.every.split(/\s+/);
|
||||
if (parts.length === 6) {
|
||||
const second = parts[0];
|
||||
const minute = parts[1];
|
||||
const hour = parts[2];
|
||||
const dayOfMonth = parts[3];
|
||||
|
||||
if (second === "0" && dayOfMonth.startsWith("*/")) {
|
||||
scheduleType.value = "daily";
|
||||
dayInterval.value = dayOfMonth.substring(2);
|
||||
selectedTime.value = { hour, minute };
|
||||
} else if (second === "0" && dayOfMonth === "*" && parts[4] === "*" && parts[5] === "*") {
|
||||
scheduleType.value = "daily";
|
||||
dayInterval.value = "1";
|
||||
selectedTime.value = { hour, minute };
|
||||
} else {
|
||||
scheduleType.value = "custom";
|
||||
customCron.value = task.value.every;
|
||||
}
|
||||
} else if (parts.length === 5) {
|
||||
const minute = parts[0];
|
||||
const hour = parts[1];
|
||||
const dayOfMonth = parts[2];
|
||||
|
||||
if (dayOfMonth.startsWith("*/")) {
|
||||
scheduleType.value = "daily";
|
||||
dayInterval.value = dayOfMonth.substring(2);
|
||||
selectedTime.value = { hour, minute };
|
||||
} else if (dayOfMonth === "*" && parts[3] === "*" && parts[4] === "*") {
|
||||
scheduleType.value = "daily";
|
||||
dayInterval.value = "1";
|
||||
selectedTime.value = { hour, minute };
|
||||
} else {
|
||||
scheduleType.value = "custom";
|
||||
customCron.value = `0 ${task.value.every}`;
|
||||
}
|
||||
} else {
|
||||
scheduleType.value = "custom";
|
||||
customCron.value = task.value.every;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function show(taskData?: ServerSchedule | Schedule) {
|
||||
if (taskData) {
|
||||
loadTaskData(taskData);
|
||||
} else {
|
||||
resetForm();
|
||||
}
|
||||
modal.value?.show();
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
modal.value?.hide();
|
||||
}
|
||||
|
||||
function onModalHide() {
|
||||
// Reset form when modal is hidden
|
||||
resetForm();
|
||||
}
|
||||
|
||||
async function saveTask() {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
|
||||
if (isValidCron.value) {
|
||||
task.value.every = cronString.value;
|
||||
} else {
|
||||
error.value = "Cannot save with invalid cron expression.";
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (isNew.value) {
|
||||
const scheduleToCreate: Schedule = {
|
||||
title: task.value.title || "",
|
||||
every: task.value.every!,
|
||||
action_kind: task.value.action_kind!,
|
||||
options: task.value.options!,
|
||||
enabled: task.value.enabled !== undefined ? task.value.enabled : true,
|
||||
warn_msg: task.value.warn_msg !== undefined ? task.value.warn_msg : "",
|
||||
warn_intervals: task.value.warn_intervals || [],
|
||||
};
|
||||
await props.server.scheduling.createTask(scheduleToCreate);
|
||||
closeModal();
|
||||
} else if (originalTaskId.value != null) {
|
||||
await props.server.scheduling.editTask(originalTaskId.value, task.value);
|
||||
closeModal();
|
||||
}
|
||||
} catch (e) {
|
||||
error.value = (e as Error).message || "Failed to save task.";
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
watch([cronString, isValidCron], ([cron, valid]) => {
|
||||
if (valid) {
|
||||
task.value.every = cron;
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => task.value.action_kind,
|
||||
(kind) => {
|
||||
if (kind === "game-command") {
|
||||
if (
|
||||
!task.value.options ||
|
||||
typeof task.value.options !== "object" ||
|
||||
!("command" in task.value.options)
|
||||
) {
|
||||
task.value.options = { command: "" };
|
||||
}
|
||||
} else {
|
||||
task.value.options = {};
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
hide: closeModal,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@ -11,6 +11,7 @@ import {
|
||||
WSModule,
|
||||
FSModule,
|
||||
} from "./modules/index.ts";
|
||||
import { SchedulingModule } from "./modules/scheduling.ts";
|
||||
|
||||
export function handleError(err: any) {
|
||||
if (err instanceof ModrinthServerError && err.v1Error) {
|
||||
@ -40,6 +41,7 @@ export class ModrinthServer {
|
||||
readonly startup: StartupModule;
|
||||
readonly ws: WSModule;
|
||||
readonly fs: FSModule;
|
||||
readonly scheduling: SchedulingModule;
|
||||
|
||||
constructor(serverId: string) {
|
||||
this.serverId = serverId;
|
||||
@ -51,6 +53,7 @@ export class ModrinthServer {
|
||||
this.startup = new StartupModule(this);
|
||||
this.ws = new WSModule(this);
|
||||
this.fs = new FSModule(this);
|
||||
this.scheduling = new SchedulingModule(this);
|
||||
}
|
||||
|
||||
async createMissingFolders(path: string): Promise<void> {
|
||||
@ -197,7 +200,16 @@ export class ModrinthServer {
|
||||
const modulesToRefresh =
|
||||
modules.length > 0
|
||||
? modules
|
||||
: (["general", "content", "backups", "network", "startup", "ws", "fs"] as ModuleName[]);
|
||||
: ([
|
||||
"general",
|
||||
"content",
|
||||
"backups",
|
||||
"network",
|
||||
"startup",
|
||||
"ws",
|
||||
"fs",
|
||||
"scheduling",
|
||||
] as ModuleName[]);
|
||||
|
||||
for (const module of modulesToRefresh) {
|
||||
try {
|
||||
@ -242,6 +254,8 @@ export class ModrinthServer {
|
||||
case "fs":
|
||||
await this.fs.fetch();
|
||||
break;
|
||||
case "scheduling":
|
||||
await this.scheduling.fetch();
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof ModrinthServerError) {
|
||||
|
||||
80
apps/frontend/src/composables/servers/modules/scheduling.ts
Normal file
80
apps/frontend/src/composables/servers/modules/scheduling.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import type { Schedule, ServerSchedule } from "@modrinth/utils";
|
||||
import { useServersFetch } from "../servers-fetch.ts";
|
||||
import { ServerModule } from "./base.ts";
|
||||
|
||||
export class SchedulingModule extends ServerModule {
|
||||
tasks: ServerSchedule[] = [];
|
||||
|
||||
private optimisticUpdate(action: () => void): () => void {
|
||||
const originalTasks = [...this.tasks];
|
||||
action();
|
||||
return () => {
|
||||
this.tasks = originalTasks;
|
||||
};
|
||||
}
|
||||
|
||||
async fetch(): Promise<void> {
|
||||
const response = await useServersFetch<{ schedules: { quota: 32; items: ServerSchedule[] } }>(
|
||||
`servers/${this.serverId}/options`,
|
||||
{ version: 1 },
|
||||
);
|
||||
this.tasks = response.schedules.items;
|
||||
}
|
||||
|
||||
async deleteTask(task: ServerSchedule): Promise<void> {
|
||||
const rollback = this.optimisticUpdate(() => {
|
||||
this.tasks = this.tasks.filter((t) => t.id !== task.id);
|
||||
});
|
||||
|
||||
try {
|
||||
await useServersFetch(`servers/${this.serverId}/options/schedules/${task.id}`, {
|
||||
method: "DELETE",
|
||||
version: 1,
|
||||
});
|
||||
} catch (error) {
|
||||
rollback();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async createTask(task: Schedule): Promise<number> {
|
||||
const rollback = this.optimisticUpdate(() => {});
|
||||
|
||||
try {
|
||||
const response = await useServersFetch<{ id: number }>(
|
||||
`servers/${this.serverId}/options/schedules`,
|
||||
{
|
||||
method: "POST",
|
||||
body: task,
|
||||
version: 1,
|
||||
},
|
||||
);
|
||||
|
||||
this.tasks.push({ ...task, id: response.id } as ServerSchedule);
|
||||
return response.id;
|
||||
} catch (error) {
|
||||
rollback();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async editTask(taskId: number, updatedTask: Partial<Schedule>): Promise<void> {
|
||||
const rollback = this.optimisticUpdate(() => {
|
||||
const taskIndex = this.tasks.findIndex((t) => t.id === taskId);
|
||||
if (taskIndex !== -1) {
|
||||
this.tasks[taskIndex] = { ...this.tasks[taskIndex], ...updatedTask };
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await useServersFetch(`servers/${this.serverId}/options/schedules/${taskId}`, {
|
||||
method: "PATCH",
|
||||
body: updatedTask,
|
||||
version: 1,
|
||||
});
|
||||
} catch (error) {
|
||||
rollback();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -417,7 +417,7 @@ const loadModulesPromise = Promise.resolve().then(() => {
|
||||
if (server.general?.status === "suspended") {
|
||||
return;
|
||||
}
|
||||
return server.refresh(["content", "backups", "network", "startup", "fs"]);
|
||||
return server.refresh(["content", "backups", "network", "startup", "fs", "scheduling"]);
|
||||
});
|
||||
|
||||
provide("modulesLoaded", loadModulesPromise);
|
||||
|
||||
@ -16,6 +16,7 @@ import {
|
||||
CardIcon,
|
||||
UserIcon,
|
||||
WrenchIcon,
|
||||
CalendarSyncIcon,
|
||||
} from "@modrinth/assets";
|
||||
import { ModrinthServer } from "~/composables/servers/modrinth-servers.ts";
|
||||
import type { BackupInProgressReason } from "~/pages/servers/manage/[id].vue";
|
||||
@ -35,6 +36,11 @@ useHead({
|
||||
const navLinks = [
|
||||
{ icon: SettingsIcon, label: "General", href: `/servers/manage/${serverId}/options` },
|
||||
{ icon: WrenchIcon, label: "Platform", href: `/servers/manage/${serverId}/options/loader` },
|
||||
{
|
||||
icon: CalendarSyncIcon,
|
||||
label: "Task Scheduling",
|
||||
href: `/servers/manage/${serverId}/options/scheduling`,
|
||||
},
|
||||
{ icon: TextQuoteIcon, label: "Startup", href: `/servers/manage/${serverId}/options/startup` },
|
||||
{ icon: VersionIcon, label: "Network", href: `/servers/manage/${serverId}/options/network` },
|
||||
{ icon: ListIcon, label: "Properties", href: `/servers/manage/${serverId}/options/properties` },
|
||||
|
||||
@ -0,0 +1,437 @@
|
||||
<template>
|
||||
<EditScheduledTaskModal ref="modal" :server="server"></EditScheduledTaskModal>
|
||||
<div class="relative h-full w-full overflow-y-auto">
|
||||
<div class="flex h-full w-full flex-col">
|
||||
<section class="universal-card">
|
||||
<div class="mb-6 flex items-center justify-between">
|
||||
<div class="flex h-full flex-col justify-center">
|
||||
<h2 class="m-0 text-lg font-bold text-contrast">Task scheduling</h2>
|
||||
<span v-if="tasks.length < 1">
|
||||
No scheduled tasks yet. Click the button to create your first task.
|
||||
</span>
|
||||
<span v-else-if="!isMobile"
|
||||
>You can manage multiple tasks at once by selecting them below.</span
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<ButtonStyled color="green"
|
||||
><button @click="modal?.show()"><PlusIcon /> Create task</button></ButtonStyled
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="tasks.length > 0">
|
||||
<div v-if="!isMobile" class="input-group">
|
||||
<ButtonStyled>
|
||||
<button :disabled="selectedTasks.length === 0" @click="handleBulkToggle">
|
||||
<ToggleRightIcon />
|
||||
Toggle selected
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled color="red">
|
||||
<button :disabled="selectedTasks.length === 0" @click="handleBulkDelete">
|
||||
<TrashIcon />
|
||||
Delete selected
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<div class="push-right">
|
||||
<div class="labeled-control-row">
|
||||
Sort by
|
||||
<Multiselect
|
||||
v-model="sortBy"
|
||||
:searchable="false"
|
||||
class="small-select"
|
||||
:options="['Name', 'Type', 'Enabled', 'Schedule']"
|
||||
:close-on-select="true"
|
||||
:show-labels="false"
|
||||
:allow-empty="false"
|
||||
@update:model-value="updateSort"
|
||||
/>
|
||||
<button
|
||||
v-tooltip="descending ? 'Descending' : 'Ascending'"
|
||||
class="square-button"
|
||||
@click="updateDescending"
|
||||
>
|
||||
<DescendingIcon v-if="descending" />
|
||||
<AscendingIcon v-else />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!isMobile" class="grid-table">
|
||||
<div class="grid-table__row grid-table__header">
|
||||
<div>
|
||||
<Checkbox
|
||||
:model-value="selectedTasks.length === tasks.length && tasks.length > 0"
|
||||
@update:model-value="handleSelectAll"
|
||||
/>
|
||||
</div>
|
||||
<div>Type</div>
|
||||
<div>Task Details</div>
|
||||
<div class="schedule-col">Schedule</div>
|
||||
<div class="details-col">Warnings</div>
|
||||
<div>Enabled</div>
|
||||
<div>Actions</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="(task, index) in sortedTasks"
|
||||
:key="`task-${index}`"
|
||||
class="grid-table__row"
|
||||
>
|
||||
<div>
|
||||
<Checkbox
|
||||
:model-value="selectedTasks.includes(task)"
|
||||
@update:model-value="(value) => handleTaskSelect(task, value)"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<RaisedBadge
|
||||
:text="task.action_kind === 'restart' ? 'Restart' : 'Game Command'"
|
||||
:icon="task.action_kind === 'restart' ? UpdatedIcon : CodeIcon"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<span class="mb-1 block font-medium text-primary">{{ task.title }}</span>
|
||||
<div
|
||||
v-if="task.action_kind === 'game-command' && task.options?.command"
|
||||
class="mt-1"
|
||||
>
|
||||
<code
|
||||
class="break-all rounded-sm bg-button-bg px-1 py-0.5 text-xs text-secondary"
|
||||
>
|
||||
{{ task.options.command }}
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
<div class="schedule-col">
|
||||
<span class="text-sm text-secondary">{{ getHumanReadableCron(task.every) }}</span>
|
||||
</div>
|
||||
<div class="details-col">
|
||||
<div
|
||||
v-if="task.warn_intervals && task.warn_intervals.length > 0"
|
||||
class="flex flex-col gap-1"
|
||||
>
|
||||
<span class="text-sm font-medium text-primary">
|
||||
{{ task.warn_intervals.length }} warnings
|
||||
</span>
|
||||
<div class="font-mono text-xs text-secondary">
|
||||
{{ formatWarningIntervals(task.warn_intervals) }}
|
||||
</div>
|
||||
</div>
|
||||
<span v-else class="text-sm italic text-secondary">No warnings</span>
|
||||
</div>
|
||||
<div>
|
||||
<Toggle
|
||||
:model-value="task.enabled"
|
||||
@update:model-value="(value) => handleTaskToggle(task, value || false)"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="flex gap-1">
|
||||
<ButtonStyled icon-only circular>
|
||||
<button :v-tooltip="'Edit Task'" @click="modal?.show(task)">
|
||||
<EditIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled icon-only circular color="red">
|
||||
<button @click="handleTaskDelete(task)">
|
||||
<TrashIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="mt-4 flex flex-col gap-3">
|
||||
<Card
|
||||
v-for="(task, index) in sortedTasks"
|
||||
:key="`mobile-task-${index}`"
|
||||
class="rounded-lg border !bg-bg p-4 shadow-sm"
|
||||
>
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<h3 class="mb-0 truncate font-medium">{{ task.title }}</h3>
|
||||
<Toggle
|
||||
:model-value="task.enabled"
|
||||
@update:model-value="(value) => handleTaskToggle(task, value || false)"
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-2 flex items-center gap-2">
|
||||
<RaisedBadge
|
||||
:text="task.action_kind === 'restart' ? 'Restart' : 'Command'"
|
||||
:icon="task.action_kind === 'restart' ? UpdatedIcon : CodeIcon"
|
||||
class="text-xs"
|
||||
/>
|
||||
<div class="ml-auto flex flex-row gap-2">
|
||||
<ButtonStyled icon-only circular>
|
||||
<button class="p-1" @click="modal?.show(task)">
|
||||
<EditIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled icon-only circular color="red">
|
||||
<button class="p-1" @click="handleTaskDelete(task)">
|
||||
<TrashIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted, onBeforeMount } from "vue";
|
||||
import { Multiselect } from "vue-multiselect";
|
||||
import {
|
||||
PlusIcon,
|
||||
TrashIcon,
|
||||
ToggleRightIcon,
|
||||
EditIcon,
|
||||
UpdatedIcon,
|
||||
CodeIcon,
|
||||
SortAscendingIcon as AscendingIcon,
|
||||
SortDescendingIcon as DescendingIcon,
|
||||
} from "@modrinth/assets";
|
||||
import { Toggle, Checkbox, RaisedBadge, ButtonStyled, Card } from "@modrinth/ui";
|
||||
import cronstrue from "cronstrue";
|
||||
import type { ServerSchedule } from "@modrinth/utils";
|
||||
import { ModrinthServer } from "~/composables/servers/modrinth-servers.ts";
|
||||
import EditScheduledTaskModal from "~/components/ui/servers/scheduling/EditScheduledTaskModal.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
server: ModrinthServer;
|
||||
}>();
|
||||
|
||||
onBeforeMount(async () => {
|
||||
await props.server.scheduling.fetch();
|
||||
});
|
||||
|
||||
const selectedTasks = ref<ServerSchedule[]>([]);
|
||||
const sortBy = ref("Name");
|
||||
const descending = ref(false);
|
||||
const modal = ref<typeof EditScheduledTaskModal>();
|
||||
const isMobile = ref(true);
|
||||
|
||||
const tasks = computed(() => props.server.scheduling.tasks as ServerSchedule[]);
|
||||
|
||||
const sortedTasks = computed(() => {
|
||||
const sorted = [...tasks.value];
|
||||
|
||||
switch (sortBy.value) {
|
||||
case "Name":
|
||||
sorted.sort((a, b) => a.title.localeCompare(b.title));
|
||||
break;
|
||||
case "Type":
|
||||
sorted.sort((a, b) => a.action_kind.localeCompare(b.action_kind));
|
||||
break;
|
||||
case "Enabled":
|
||||
sorted.sort((a, b) => {
|
||||
if (a.enabled === b.enabled) return 0;
|
||||
return a.enabled ? -1 : 1;
|
||||
});
|
||||
break;
|
||||
case "Schedule":
|
||||
sorted.sort((a, b) => a.every.localeCompare(b.every));
|
||||
break;
|
||||
}
|
||||
|
||||
return descending.value ? sorted.reverse() : sorted;
|
||||
});
|
||||
|
||||
function checkMobile() {
|
||||
isMobile.value = window.innerWidth < 874;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
checkMobile();
|
||||
window.addEventListener("resize", checkMobile);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener("resize", checkMobile);
|
||||
});
|
||||
|
||||
function handleSelectAll(selected: boolean): void {
|
||||
selectedTasks.value = selected ? [...tasks.value] : [];
|
||||
}
|
||||
|
||||
function handleTaskSelect(task: ServerSchedule, selected: boolean): void {
|
||||
if (selected) {
|
||||
selectedTasks.value.push(task);
|
||||
} else {
|
||||
selectedTasks.value = selectedTasks.value.filter((t) => t !== task);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleTaskToggle(task: ServerSchedule, enabled: boolean): Promise<void> {
|
||||
try {
|
||||
await props.server.scheduling.editTask(task.id, { enabled });
|
||||
console.log("Toggle task:", task.id, enabled);
|
||||
} catch (error) {
|
||||
console.error("Failed to toggle task:", error);
|
||||
task.enabled = !enabled;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleTaskDelete(task: ServerSchedule): Promise<void> {
|
||||
if (confirm(`Are you sure you want to delete "${task.title}"?`)) {
|
||||
try {
|
||||
await props.server.scheduling.deleteTask(task);
|
||||
selectedTasks.value = selectedTasks.value.filter((t) => t !== task);
|
||||
console.log("Delete task:", task.title);
|
||||
} catch (error) {
|
||||
console.error("Failed to delete task:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handleBulkToggle(): Promise<void> {
|
||||
const enabledCount = selectedTasks.value.filter((t) => t.enabled).length;
|
||||
const shouldEnable = enabledCount < selectedTasks.value.length / 2;
|
||||
|
||||
try {
|
||||
await Promise.all(
|
||||
selectedTasks.value.map((task) =>
|
||||
props.server.scheduling.editTask(task.id, { enabled: shouldEnable }),
|
||||
),
|
||||
);
|
||||
console.log("Bulk toggle tasks:", selectedTasks.value.length, "to", shouldEnable);
|
||||
} catch (error) {
|
||||
console.error("Failed to bulk toggle tasks:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleBulkDelete(): Promise<void> {
|
||||
if (confirm(`Are you sure you want to delete ${selectedTasks.value.length} selected tasks?`)) {
|
||||
try {
|
||||
await Promise.all(
|
||||
selectedTasks.value.map((task) => props.server.scheduling.deleteTask(task)),
|
||||
);
|
||||
selectedTasks.value = [];
|
||||
console.log("Bulk delete completed");
|
||||
} catch (error) {
|
||||
console.error("Failed to bulk delete tasks:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateSort(): void {
|
||||
// Trigger reactivity for sortedTasks
|
||||
}
|
||||
|
||||
function updateDescending(): void {
|
||||
descending.value = !descending.value;
|
||||
}
|
||||
|
||||
function getHumanReadableCron(cronExpression: string): string {
|
||||
try {
|
||||
return cronstrue.toString(cronExpression);
|
||||
} catch {
|
||||
return cronExpression;
|
||||
}
|
||||
}
|
||||
|
||||
function formatWarningIntervals(intervals: number[]): string {
|
||||
return intervals
|
||||
.sort((a, b) => b - a)
|
||||
.map((seconds) => {
|
||||
if (seconds >= 3600) return `${Math.floor(seconds / 3600)}h`;
|
||||
if (seconds >= 60) return `${Math.floor(seconds / 60)}m`;
|
||||
return `${seconds}s`;
|
||||
})
|
||||
.join(", ");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.grid-table {
|
||||
display: grid;
|
||||
grid-template-columns:
|
||||
min-content minmax(min-content, 120px) minmax(min-content, 2fr)
|
||||
minmax(min-content, 1fr) minmax(min-content, 120px) min-content min-content;
|
||||
border-radius: var(--size-rounded-sm);
|
||||
overflow: hidden;
|
||||
margin-top: var(--spacing-card-md);
|
||||
outline: 1px solid transparent;
|
||||
|
||||
.grid-table__row {
|
||||
display: contents;
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: var(--spacing-card-sm);
|
||||
|
||||
&:first-child {
|
||||
padding-left: var(--spacing-card-bg);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-right: var(--spacing-card-bg);
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(2n + 1) > div {
|
||||
background-color: var(--color-table-alternate-row);
|
||||
}
|
||||
|
||||
&.grid-table__header > div {
|
||||
background-color: var(--color-bg);
|
||||
font-weight: bold;
|
||||
color: var(--color-text-dark);
|
||||
padding-top: var(--spacing-card-bg);
|
||||
padding-bottom: var(--spacing-card-bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.labeled-control-row {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
gap: var(--spacing-card-md);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.small-select {
|
||||
width: -moz-fit-content;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.push-right {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 1050px) {
|
||||
.schedule-col {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.grid-table {
|
||||
grid-template-columns:
|
||||
min-content minmax(min-content, 120px) minmax(min-content, 2fr) minmax(min-content, 120px)
|
||||
min-content min-content;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1010px) {
|
||||
.details-col {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.grid-table {
|
||||
grid-template-columns:
|
||||
min-content minmax(min-content, 120px) minmax(min-content, 2fr) minmax(min-content, 120px)
|
||||
min-content;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
12
packages/assets/icons/calendar-sync.svg
Normal file
12
packages/assets/icons/calendar-sync.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="lucide lucide-calendar-sync-icon lucide-calendar-sync">
|
||||
<path d="M11 10v4h4"/>
|
||||
<path d="m11 14 1.535-1.605a5 5 0 0 1 8 1.5"/>
|
||||
<path d="M16 2v4"/>
|
||||
<path d="m21 18-1.535 1.605a5 5 0 0 1-8-1.5"/>
|
||||
<path d="M21 22v-4h-4"/>
|
||||
<path d="M21 8.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h4.3"/>
|
||||
<path d="M3 10h4"/>
|
||||
<path d="M8 2v4"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 551 B |
1
packages/assets/icons/clock.svg
Normal file
1
packages/assets/icons/clock.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-clock-icon lucide-clock"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
||||
|
After Width: | Height: | Size: 302 B |
1
packages/assets/icons/toggle-right.svg
Normal file
1
packages/assets/icons/toggle-right.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-toggle-right-icon lucide-toggle-right"><circle cx="15" cy="12" r="3"/><rect width="20" height="14" x="2" y="5" rx="7"/></svg>
|
||||
|
After Width: | Height: | Size: 327 B |
1
packages/assets/icons/triangle-alert.svg
Normal file
1
packages/assets/icons/triangle-alert.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-triangle-alert-icon lucide-triangle-alert"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>
|
||||
|
After Width: | Height: | Size: 376 B |
@ -66,6 +66,7 @@ import _ChevronRightIcon from './icons/chevron-right.svg?component'
|
||||
import _ClearIcon from './icons/clear.svg?component'
|
||||
import _ClientIcon from './icons/client.svg?component'
|
||||
import _ClipboardCopyIcon from './icons/clipboard-copy.svg?component'
|
||||
import _ClockIcon from './icons/clock.svg?component'
|
||||
import _CodeIcon from './icons/code.svg?component'
|
||||
import _CoffeeIcon from './icons/coffee.svg?component'
|
||||
import _CoinsIcon from './icons/coins.svg?component'
|
||||
@ -182,6 +183,7 @@ import _TagsIcon from './icons/tags.svg?component'
|
||||
import _TerminalSquareIcon from './icons/terminal-square.svg?component'
|
||||
import _TransferIcon from './icons/transfer.svg?component'
|
||||
import _TrashIcon from './icons/trash.svg?component'
|
||||
import _TriangleAlertIcon from './icons/triangle-alert.svg?component'
|
||||
import _UndoIcon from './icons/undo.svg?component'
|
||||
import _RedoIcon from './icons/redo.svg?component'
|
||||
import _UnknownIcon from './icons/unknown.svg?component'
|
||||
@ -210,6 +212,8 @@ import _CPUIcon from './icons/cpu.svg?component'
|
||||
import _LoaderIcon from './icons/loader.svg?component'
|
||||
import _ImportIcon from './icons/import.svg?component'
|
||||
import _TimerIcon from './icons/timer.svg?component'
|
||||
import _CalendarSyncIcon from './icons/calendar-sync.svg?component'
|
||||
import _ToggleRightIcon from './icons/toggle-right.svg?component'
|
||||
|
||||
// Editor Icons
|
||||
import _BoldIcon from './icons/bold.svg?component'
|
||||
@ -285,6 +289,7 @@ export const ChevronRightIcon = _ChevronRightIcon
|
||||
export const ClearIcon = _ClearIcon
|
||||
export const ClientIcon = _ClientIcon
|
||||
export const ClipboardCopyIcon = _ClipboardCopyIcon
|
||||
export const ClockIcon = _ClockIcon
|
||||
export const CodeIcon = _CodeIcon
|
||||
export const CoffeeIcon = _CoffeeIcon
|
||||
export const CoinsIcon = _CoinsIcon
|
||||
@ -441,3 +446,6 @@ export const LoaderIcon = _LoaderIcon
|
||||
export const ImportIcon = _ImportIcon
|
||||
export const CardIcon = _CardIcon
|
||||
export const TimerIcon = _TimerIcon
|
||||
export const CalendarSyncIcon = _CalendarSyncIcon
|
||||
export const ToggleRightIcon = _ToggleRightIcon
|
||||
export const TriangleAlertIcon = _TriangleAlertIcon
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
"@types/markdown-it": "^14.1.1",
|
||||
"@vintl/how-ago": "^3.0.1",
|
||||
"apexcharts": "^3.44.0",
|
||||
"cronstrue": "^2.61.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"floating-vue": "^5.2.2",
|
||||
"highlight.js": "^11.9.0",
|
||||
|
||||
@ -4,10 +4,10 @@
|
||||
v-for="item in items"
|
||||
:key="formatLabel(item)"
|
||||
class="btn"
|
||||
:class="{ selected: selected === item, capitalize: capitalize }"
|
||||
:class="{ selected: isSelected(item), capitalize: capitalize }"
|
||||
@click="toggleItem(item)"
|
||||
>
|
||||
<CheckIcon v-if="selected === item" />
|
||||
<CheckIcon v-if="isSelected(item)" />
|
||||
<span>{{ formatLabel(item) }}</span>
|
||||
</Button>
|
||||
</div>
|
||||
@ -23,26 +23,48 @@ const props = withDefaults(
|
||||
formatLabel?: (item: T) => string
|
||||
neverEmpty?: boolean
|
||||
capitalize?: boolean
|
||||
multi?: boolean
|
||||
}>(),
|
||||
{
|
||||
neverEmpty: true,
|
||||
// Intentional any type, as this default should only be used for primitives (string or number)
|
||||
formatLabel: (item) => item.toString(),
|
||||
capitalize: true,
|
||||
multi: false,
|
||||
},
|
||||
)
|
||||
const selected = defineModel<T | null>()
|
||||
const selected = defineModel<T | null | T[]>()
|
||||
|
||||
// If one always has to be selected, default to the first one
|
||||
if (props.items.length > 0 && props.neverEmpty && !selected.value) {
|
||||
selected.value = props.items[0]
|
||||
selected.value = props.multi ? [props.items[0]] : props.items[0]
|
||||
}
|
||||
|
||||
function isSelected(item: T): boolean {
|
||||
if (props.multi) {
|
||||
return Array.isArray(selected.value) && selected.value.includes(item)
|
||||
}
|
||||
return selected.value === item
|
||||
}
|
||||
|
||||
function toggleItem(item: T) {
|
||||
if (selected.value === item && !props.neverEmpty) {
|
||||
selected.value = null
|
||||
if (props.multi) {
|
||||
const currentSelection = Array.isArray(selected.value) ? selected.value : []
|
||||
const isCurrentlySelected = currentSelection.includes(item)
|
||||
|
||||
if (isCurrentlySelected) {
|
||||
if (!props.neverEmpty || currentSelection.length > 1) {
|
||||
selected.value = currentSelection.filter((i) => i !== item)
|
||||
}
|
||||
} else {
|
||||
selected.value = [...currentSelection, item]
|
||||
}
|
||||
} else {
|
||||
selected.value = item
|
||||
if (selected.value === item && !props.neverEmpty) {
|
||||
selected.value = null
|
||||
} else {
|
||||
selected.value = item
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
17
packages/ui/src/components/base/RaisedBadge.vue
Normal file
17
packages/ui/src/components/base/RaisedBadge.vue
Normal file
@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div class="flex items-center gap-2 w-fit px-3 py-1 bg-button-bg rounded-full text-sm">
|
||||
<component :is="icon" v-if="icon" class="w-4 h-4" />
|
||||
<span class="whitespace-nowrap">
|
||||
{{ text }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Component } from 'vue'
|
||||
|
||||
defineProps<{
|
||||
text: string
|
||||
icon?: Component
|
||||
}>()
|
||||
</script>
|
||||
161
packages/ui/src/components/base/TabbedContent.vue
Normal file
161
packages/ui/src/components/base/TabbedContent.vue
Normal file
@ -0,0 +1,161 @@
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
class="card-shadow experimental-styles-within relative flex w-fit overflow-x-auto rounded-full bg-button-bg p-1 text-sm font-bold"
|
||||
>
|
||||
<button
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="tab"
|
||||
ref="tabElements"
|
||||
class="button-animation z-[1] flex flex-row items-center gap-2 px-4 py-2 focus:rounded-full bg-transparent"
|
||||
:class="{
|
||||
'text-button-textSelected': activeTabIndex === index,
|
||||
'text-contrast': activeTabIndex !== index,
|
||||
}"
|
||||
@click="setActiveTab(index)"
|
||||
>
|
||||
<span class="text-nowrap font-bold text-center mx-auto">{{ getTabLabel(tab) }}</span>
|
||||
</button>
|
||||
|
||||
<div
|
||||
:class="`tabs-transition pointer-events-none absolute h-[calc(100%-0.5rem)] overflow-hidden rounded-full p-1 bg-button-bgSelected`"
|
||||
:style="{
|
||||
left: sliderLeftPx,
|
||||
top: sliderTopPx,
|
||||
right: sliderRightPx,
|
||||
bottom: sliderBottomPx,
|
||||
opacity:
|
||||
sliderLeft === 4 && sliderLeft === sliderRight ? 0 : activeTabIndex === -1 ? 0 : 1,
|
||||
}"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Tab Content -->
|
||||
<div class="tab-content mt-4">
|
||||
<template v-for="(tab, index) in tabs" :key="tab">
|
||||
<div v-show="activeTabIndex === index" class="tab-panel">
|
||||
<slot :name="tab" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted, nextTick } from 'vue'
|
||||
|
||||
interface Props {
|
||||
tabs: string[]
|
||||
formatFunction?: (tab: string) => string
|
||||
defaultTab?: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
formatFunction: undefined,
|
||||
defaultTab: undefined,
|
||||
})
|
||||
|
||||
const activeTabIndex = ref(0)
|
||||
const tabElements = ref<HTMLElement[]>([])
|
||||
|
||||
const sliderLeft = ref(4)
|
||||
const sliderTop = ref(4)
|
||||
const sliderRight = ref(4)
|
||||
const sliderBottom = ref(4)
|
||||
|
||||
const sliderLeftPx = computed(() => `${sliderLeft.value}px`)
|
||||
const sliderTopPx = computed(() => `${sliderTop.value}px`)
|
||||
const sliderRightPx = computed(() => `${sliderRight.value}px`)
|
||||
const sliderBottomPx = computed(() => `${sliderBottom.value}px`)
|
||||
|
||||
function getTabLabel(tab: string): string {
|
||||
return props.formatFunction ? props.formatFunction(tab) : tab
|
||||
}
|
||||
|
||||
function setActiveTab(index: number) {
|
||||
activeTabIndex.value = index
|
||||
updateSliderPosition()
|
||||
}
|
||||
|
||||
function updateSliderPosition() {
|
||||
nextTick(() => {
|
||||
const el = tabElements.value[activeTabIndex.value]
|
||||
|
||||
if (!el || !el.offsetParent) return
|
||||
|
||||
const parent = el.offsetParent as HTMLElement
|
||||
|
||||
const newValues = {
|
||||
left: el.offsetLeft,
|
||||
top: el.offsetTop,
|
||||
right: parent.offsetWidth - el.offsetLeft - el.offsetWidth,
|
||||
bottom: parent.offsetHeight - el.offsetTop - el.offsetHeight,
|
||||
}
|
||||
|
||||
if (sliderLeft.value === 4 && sliderRight.value === 4) {
|
||||
// Initial position
|
||||
sliderLeft.value = newValues.left
|
||||
sliderRight.value = newValues.right
|
||||
sliderTop.value = newValues.top
|
||||
sliderBottom.value = newValues.bottom
|
||||
} else {
|
||||
const delay = 200
|
||||
|
||||
if (newValues.left < sliderLeft.value) {
|
||||
sliderLeft.value = newValues.left
|
||||
setTimeout(() => {
|
||||
sliderRight.value = newValues.right
|
||||
}, delay)
|
||||
} else {
|
||||
sliderRight.value = newValues.right
|
||||
setTimeout(() => {
|
||||
sliderLeft.value = newValues.left
|
||||
}, delay)
|
||||
}
|
||||
|
||||
if (newValues.top < sliderTop.value) {
|
||||
sliderTop.value = newValues.top
|
||||
setTimeout(() => {
|
||||
sliderBottom.value = newValues.bottom
|
||||
}, delay)
|
||||
} else {
|
||||
sliderBottom.value = newValues.bottom
|
||||
setTimeout(() => {
|
||||
sliderTop.value = newValues.top
|
||||
}, delay)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.defaultTab) {
|
||||
const defaultIndex = props.tabs.indexOf(props.defaultTab)
|
||||
if (defaultIndex !== -1) {
|
||||
activeTabIndex.value = defaultIndex
|
||||
}
|
||||
}
|
||||
updateSliderPosition()
|
||||
})
|
||||
|
||||
watch(activeTabIndex, () => {
|
||||
updateSliderPosition()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tabs-transition {
|
||||
transition:
|
||||
all 150ms cubic-bezier(0.4, 0, 0.2, 1),
|
||||
opacity 250ms cubic-bezier(0.5, 0, 0.2, 1) 50ms;
|
||||
}
|
||||
|
||||
.card-shadow {
|
||||
box-shadow: var(--shadow-card);
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
min-height: 200px;
|
||||
}
|
||||
</style>
|
||||
264
packages/ui/src/components/base/TimePicker.vue
Normal file
264
packages/ui/src/components/base/TimePicker.vue
Normal file
@ -0,0 +1,264 @@
|
||||
<template>
|
||||
<Dropdown
|
||||
ref="dropdown"
|
||||
:disabled="disabled"
|
||||
placement="bottom-start"
|
||||
theme="ribbit-popout"
|
||||
:distance="8"
|
||||
no-arrow
|
||||
@apply-show="onDropdownShow"
|
||||
>
|
||||
<ButtonStyled
|
||||
:class="['w-full justify-start text-left font-normal', !modelValue && 'text-secondary']"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<button>
|
||||
<ClockIcon class="h-4 w-4" />
|
||||
{{ modelValue ? formatTime(modelValue) : placeholder }} {{ useUtcValues ? 'UTC' : '' }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
|
||||
<template #popper>
|
||||
<div class="flex flex-col gap-4 p-4 w-64">
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div class="flex flex-col gap-2">
|
||||
<label for="hour" class="text-sm font-medium text-contrast"> Hour </label>
|
||||
<input
|
||||
id="hour"
|
||||
v-model="currentTime.hour"
|
||||
type="text"
|
||||
inputmode="numeric"
|
||||
placeholder="00"
|
||||
class="bg-bg-input w-full rounded-lg p-2 text-center"
|
||||
maxlength="2"
|
||||
@input="handleHourChange"
|
||||
/>
|
||||
<div class="text-xs text-secondary text-center">0-23</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<label for="minute" class="text-sm font-medium text-contrast"> Minute </label>
|
||||
<input
|
||||
id="minute"
|
||||
v-model="currentTime.minute"
|
||||
type="text"
|
||||
inputmode="numeric"
|
||||
placeholder="00"
|
||||
class="bg-bg-input w-full rounded-lg p-2 text-center"
|
||||
maxlength="2"
|
||||
@input="handleMinuteChange"
|
||||
/>
|
||||
<div class="text-xs text-secondary text-center">0-59</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center p-3 bg-bg-raised rounded-lg">
|
||||
<div class="text-sm text-secondary">Selected Time (Local)</div>
|
||||
<div class="text-2xl font-bold text-contrast">
|
||||
{{ formatTime(currentTime) }}
|
||||
</div>
|
||||
<div class="text-xs text-secondary mt-1">
|
||||
{{ getUTCTime(currentTime) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="text-sm font-medium text-contrast">Quick Select</div>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<ButtonStyled v-for="preset in quickSelects" :key="preset.label">
|
||||
<button class="" @click="handleQuickSelect(preset.hour, preset.minute)">
|
||||
{{ preset.label }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 pt-2">
|
||||
<ButtonStyled class="flex-1">
|
||||
<button @click="handleCancel">Cancel</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled color="brand" class="flex-1">
|
||||
<button @click="handleDone">Done</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Dropdown>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch } from 'vue'
|
||||
import { Dropdown } from 'floating-vue'
|
||||
import { ButtonStyled } from '@modrinth/ui'
|
||||
import { ClockIcon } from '@modrinth/assets'
|
||||
|
||||
interface TimeValue {
|
||||
hour: string
|
||||
minute: string
|
||||
}
|
||||
|
||||
interface Props {
|
||||
modelValue?: TimeValue
|
||||
disabled?: boolean
|
||||
placeholder?: string
|
||||
useUtcValues?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: () => ({ hour: '12', minute: '00' }),
|
||||
disabled: false,
|
||||
placeholder: 'Select time',
|
||||
useUtcValues: false,
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: TimeValue]
|
||||
}>()
|
||||
|
||||
function utcToLocal(utcTime: TimeValue): TimeValue {
|
||||
const today = new Date()
|
||||
const utcHour = utcTime.hour === '' ? 0 : parseInt(utcTime.hour)
|
||||
const utcMinute = utcTime.minute === '' ? 0 : parseInt(utcTime.minute)
|
||||
|
||||
const utcDate = new Date(
|
||||
Date.UTC(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate(), utcHour, utcMinute),
|
||||
)
|
||||
|
||||
return {
|
||||
hour: utcDate.getHours().toString(),
|
||||
minute: utcDate.getMinutes().toString(),
|
||||
}
|
||||
}
|
||||
|
||||
function localToUtc(localTime: TimeValue): TimeValue {
|
||||
const today = new Date()
|
||||
const localHour = localTime.hour === '' ? 0 : parseInt(localTime.hour)
|
||||
const localMinute = localTime.minute === '' ? 0 : parseInt(localTime.minute)
|
||||
|
||||
const localDate = new Date(
|
||||
today.getFullYear(),
|
||||
today.getMonth(),
|
||||
today.getDate(),
|
||||
localHour,
|
||||
localMinute,
|
||||
)
|
||||
|
||||
return {
|
||||
hour: localDate.getUTCHours().toString(),
|
||||
minute: localDate.getUTCMinutes().toString(),
|
||||
}
|
||||
}
|
||||
|
||||
function emitTime(localTime: TimeValue) {
|
||||
const timeToEmit = props.useUtcValues ? localToUtc(localTime) : localTime
|
||||
emit('update:modelValue', timeToEmit)
|
||||
}
|
||||
|
||||
const dropdown = ref()
|
||||
const originalTime = ref<TimeValue>({ hour: '12', minute: '00' })
|
||||
|
||||
const getInitialTime = (): TimeValue => {
|
||||
const defaultTime = { hour: '12', minute: '00' }
|
||||
if (!props.modelValue) return defaultTime
|
||||
|
||||
return props.useUtcValues ? utcToLocal(props.modelValue) : props.modelValue
|
||||
}
|
||||
|
||||
const currentTime = reactive<TimeValue>(getInitialTime())
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
const displayTime = props.useUtcValues ? utcToLocal(newValue) : newValue
|
||||
currentTime.hour = displayTime.hour
|
||||
currentTime.minute = displayTime.minute
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
function formatTime(time: TimeValue): string {
|
||||
const hour = (time.hour === '' ? '0' : time.hour).padStart(2, '0')
|
||||
const minute = (time.minute === '' ? '0' : time.minute).padStart(2, '0')
|
||||
return `${hour}:${minute}`
|
||||
}
|
||||
|
||||
function getUTCTime(time: TimeValue): string {
|
||||
const today = new Date()
|
||||
const hourValue = time.hour === '' ? 0 : parseInt(time.hour)
|
||||
const minuteValue = time.minute === '' ? 0 : parseInt(time.minute)
|
||||
|
||||
const localDate = new Date(
|
||||
today.getFullYear(),
|
||||
today.getMonth(),
|
||||
today.getDate(),
|
||||
hourValue,
|
||||
minuteValue,
|
||||
)
|
||||
|
||||
const utcHour = localDate.getUTCHours().toString().padStart(2, '0')
|
||||
const utcMinute = localDate.getUTCMinutes().toString().padStart(2, '0')
|
||||
|
||||
return `${utcHour}:${utcMinute} UTC`
|
||||
}
|
||||
|
||||
function handleHourChange(event: Event) {
|
||||
const target = event.target as HTMLInputElement
|
||||
const cleanValue = target.value.replace(/\D/g, '').slice(0, 2)
|
||||
let hour = cleanValue
|
||||
|
||||
if (cleanValue !== '' && (parseInt(cleanValue) > 23 || parseInt(cleanValue) < 0)) {
|
||||
hour = Math.min(23, Math.max(0, parseInt(cleanValue))).toString()
|
||||
}
|
||||
|
||||
currentTime.hour = hour
|
||||
emitTime(currentTime)
|
||||
}
|
||||
|
||||
function handleMinuteChange(event: Event) {
|
||||
const target = event.target as HTMLInputElement
|
||||
const cleanValue = target.value.replace(/\D/g, '').slice(0, 2)
|
||||
let minute = cleanValue
|
||||
|
||||
if (cleanValue !== '' && (parseInt(cleanValue) > 59 || parseInt(cleanValue) < 0)) {
|
||||
minute = Math.min(59, Math.max(0, parseInt(cleanValue))).toString()
|
||||
}
|
||||
|
||||
currentTime.minute = minute
|
||||
emitTime(currentTime)
|
||||
}
|
||||
|
||||
function handleQuickSelect(hour: string, minute: string) {
|
||||
currentTime.hour = hour
|
||||
currentTime.minute = minute
|
||||
emitTime(currentTime)
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
currentTime.hour = originalTime.value.hour
|
||||
currentTime.minute = originalTime.value.minute
|
||||
emitTime(originalTime.value)
|
||||
dropdown.value?.hide()
|
||||
}
|
||||
|
||||
function handleDone() {
|
||||
dropdown.value?.hide()
|
||||
}
|
||||
|
||||
function onDropdownShow() {
|
||||
originalTime.value = { ...currentTime }
|
||||
}
|
||||
|
||||
const quickSelects = [
|
||||
{ label: '00:00', hour: '0', minute: '0' },
|
||||
{ label: '04:00', hour: '4', minute: '0' },
|
||||
{ label: '12:00', hour: '12', minute: '0' },
|
||||
{ label: '21:00', hour: '21', minute: '0' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.v-popper--theme-dropdown .v-popper__arrow-container {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@ -34,15 +34,18 @@ export { default as ProgressBar } from './base/ProgressBar.vue'
|
||||
export { default as ProjectCard } from './base/ProjectCard.vue'
|
||||
export { default as RadialHeader } from './base/RadialHeader.vue'
|
||||
export { default as RadioButtons } from './base/RadioButtons.vue'
|
||||
export { default as RaisedBadge } from './base/RaisedBadge.vue'
|
||||
export { default as ScrollablePanel } from './base/ScrollablePanel.vue'
|
||||
export { default as ServerNotice } from './base/ServerNotice.vue'
|
||||
export { default as SimpleBadge } from './base/SimpleBadge.vue'
|
||||
export { default as Slider } from './base/Slider.vue'
|
||||
export { default as SmartClickable } from './base/SmartClickable.vue'
|
||||
export { default as StatItem } from './base/StatItem.vue'
|
||||
export { default as TabbedContent } from './base/TabbedContent.vue'
|
||||
export { default as TagItem } from './base/TagItem.vue'
|
||||
export { default as TeleportDropdownMenu } from './base/TeleportDropdownMenu.vue'
|
||||
export { default as Timeline } from './base/Timeline.vue'
|
||||
export { default as TimePicker } from './base/TimePicker.vue'
|
||||
export { default as Toggle } from './base/Toggle.vue'
|
||||
|
||||
// Branding
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
<div class="overflow-y-auto p-6">
|
||||
<div class="modal-content overflow-y-auto p-6">
|
||||
<slot> You just lost the game.</slot>
|
||||
</div>
|
||||
</div>
|
||||
@ -237,6 +237,10 @@ function handleKeyDown(event: KeyboardEvent) {
|
||||
opacity: 0;
|
||||
transition: all 0.2s ease-in-out;
|
||||
|
||||
.modal-content {
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion) {
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
@ -16,4 +16,12 @@ export interface ModuleError {
|
||||
timestamp: number
|
||||
}
|
||||
|
||||
export type ModuleName = 'general' | 'content' | 'backups' | 'network' | 'startup' | 'ws' | 'fs'
|
||||
export type ModuleName =
|
||||
| 'general'
|
||||
| 'content'
|
||||
| 'backups'
|
||||
| 'network'
|
||||
| 'startup'
|
||||
| 'ws'
|
||||
| 'fs'
|
||||
| 'scheduling'
|
||||
|
||||
@ -6,3 +6,4 @@ export * from './filesystem'
|
||||
export * from './websocket'
|
||||
export * from './stats'
|
||||
export * from './common'
|
||||
export * from './scheduling'
|
||||
|
||||
19
packages/utils/servers/types/scheduling.ts
Normal file
19
packages/utils/servers/types/scheduling.ts
Normal file
@ -0,0 +1,19 @@
|
||||
export type ActionKind = 'game-command' | 'restart'
|
||||
|
||||
export type ScheduleOptions = { command: string } | Record<string, never>
|
||||
|
||||
export interface Schedule {
|
||||
title: string
|
||||
every: string
|
||||
action_kind: ActionKind
|
||||
options: ScheduleOptions
|
||||
enabled: boolean
|
||||
warn_msg: string
|
||||
warn_intervals: number[]
|
||||
}
|
||||
|
||||
export interface ServerSchedule extends Schedule {
|
||||
id: number
|
||||
server_id: string
|
||||
added_on: string
|
||||
}
|
||||
323
pnpm-lock.yaml
generated
323
pnpm-lock.yaml
generated
@ -85,7 +85,7 @@ importers:
|
||||
version: 1.11.11
|
||||
floating-vue:
|
||||
specifier: ^5.2.2
|
||||
version: 5.2.2(@nuxt/kit@3.14.1592)(vue@3.5.13(typescript@5.5.4))
|
||||
version: 5.2.2(@nuxt/kit@3.14.1592(magicast@0.3.5))(vue@3.5.13(typescript@5.5.4))
|
||||
ofetch:
|
||||
specifier: ^1.3.4
|
||||
version: 1.4.1
|
||||
@ -125,7 +125,7 @@ importers:
|
||||
version: 1.0.7(vue@3.5.13(typescript@5.5.4))
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: ^5.0.4
|
||||
version: 5.2.1(vite@5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))
|
||||
version: 5.2.1(vite@5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))
|
||||
autoprefixer:
|
||||
specifier: ^10.4.19
|
||||
version: 10.4.20(postcss@8.4.49)
|
||||
@ -158,7 +158,7 @@ importers:
|
||||
version: 5.5.4
|
||||
vite:
|
||||
specifier: ^5.4.6
|
||||
version: 5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.31.6)
|
||||
version: 5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0)
|
||||
vue-tsc:
|
||||
specifier: ^2.1.6
|
||||
version: 2.1.6(typescript@5.5.4)
|
||||
@ -178,19 +178,19 @@ importers:
|
||||
version: 0.9.4(prettier@3.3.2)(typescript@5.8.2)
|
||||
'@astrojs/starlight':
|
||||
specifier: ^0.32.2
|
||||
version: 0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1))
|
||||
version: 0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1))
|
||||
'@modrinth/assets':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/assets
|
||||
astro:
|
||||
specifier: ^5.4.1
|
||||
version: 5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1)
|
||||
version: 5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1)
|
||||
sharp:
|
||||
specifier: ^0.33.5
|
||||
version: 0.33.5
|
||||
starlight-openapi:
|
||||
specifier: ^0.14.0
|
||||
version: 0.14.0(@astrojs/markdown-remark@6.2.0)(@astrojs/starlight@0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1)))(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1))(openapi-types@12.1.3)
|
||||
version: 0.14.0(@astrojs/markdown-remark@6.2.0)(@astrojs/starlight@0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1)))(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1))(openapi-types@12.1.3)
|
||||
typescript:
|
||||
specifier: ^5.8.2
|
||||
version: 5.8.2
|
||||
@ -233,6 +233,9 @@ importers:
|
||||
ansi-to-html:
|
||||
specifier: ^0.7.2
|
||||
version: 0.7.2
|
||||
cronstrue:
|
||||
specifier: ^2.61.0
|
||||
version: 2.61.0
|
||||
dayjs:
|
||||
specifier: ^1.11.7
|
||||
version: 1.11.11
|
||||
@ -296,7 +299,7 @@ importers:
|
||||
version: 6.2.12(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.5.4))
|
||||
'@nuxt/devtools':
|
||||
specifier: ^1.3.3
|
||||
version: 1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))
|
||||
version: 1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))
|
||||
'@types/dompurify':
|
||||
specifier: ^3.0.5
|
||||
version: 3.0.5
|
||||
@ -311,7 +314,7 @@ importers:
|
||||
version: 3.0.1(@formatjs/intl@2.10.4(typescript@5.5.4))
|
||||
'@vintl/nuxt':
|
||||
specifier: ^1.9.2
|
||||
version: 1.9.2(@vue/compiler-core@3.5.13)(magicast@0.3.5)(rollup@4.28.1)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)
|
||||
version: 1.9.2(@vue/compiler-core@3.5.13)(magicast@0.3.5)(rollup@4.28.1)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)
|
||||
autoprefixer:
|
||||
specifier: ^10.4.19
|
||||
version: 10.4.20(postcss@8.4.49)
|
||||
@ -323,7 +326,7 @@ importers:
|
||||
version: 10.4.2
|
||||
nuxt:
|
||||
specifier: ^3.14.1592
|
||||
version: 3.14.1592(@parcel/watcher@2.4.1)(@types/node@20.14.11)(eslint@8.57.0)(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.31.6)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue-tsc@2.1.6(typescript@5.5.4))
|
||||
version: 3.14.1592(@parcel/watcher@2.4.1)(@types/node@20.14.11)(eslint@8.57.0)(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.42.0)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue-tsc@2.1.6(typescript@5.5.4))
|
||||
postcss:
|
||||
specifier: ^8.4.39
|
||||
version: 8.4.49
|
||||
@ -383,7 +386,7 @@ importers:
|
||||
version: 2.0.7(eslint@9.13.0(jiti@2.4.1))
|
||||
eslint-plugin-prettier:
|
||||
specifier: ^5.2.1
|
||||
version: 5.2.1(@types/eslint@9.6.0)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.4.1)))(eslint@9.13.0(jiti@2.4.1))(prettier@3.3.2)
|
||||
version: 5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.4.1)))(eslint@9.13.0(jiti@2.4.1))(prettier@3.3.2)
|
||||
eslint-plugin-unicorn:
|
||||
specifier: ^54.0.0
|
||||
version: 54.0.0(eslint@9.13.0(jiti@2.4.1))
|
||||
@ -429,12 +432,15 @@ importers:
|
||||
apexcharts:
|
||||
specifier: ^3.44.0
|
||||
version: 3.49.2
|
||||
cronstrue:
|
||||
specifier: ^2.61.0
|
||||
version: 2.61.0
|
||||
dayjs:
|
||||
specifier: ^1.11.10
|
||||
version: 1.11.11
|
||||
floating-vue:
|
||||
specifier: ^5.2.2
|
||||
version: 5.2.2(@nuxt/kit@3.14.1592(rollup@3.29.4))(vue@3.5.13(typescript@5.5.4))
|
||||
version: 5.2.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@3.29.4))(vue@3.5.13(typescript@5.5.4))
|
||||
highlight.js:
|
||||
specifier: ^11.9.0
|
||||
version: 11.9.0
|
||||
@ -468,7 +474,7 @@ importers:
|
||||
version: 7.3.1
|
||||
'@vintl/unplugin':
|
||||
specifier: ^1.5.1
|
||||
version: 1.5.2(@vue/compiler-core@3.5.13)(rollup@3.29.4)(vite@4.5.3(@types/node@22.4.1))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)
|
||||
version: 1.5.2(@vue/compiler-core@3.5.13)(rollup@3.29.4)(vite@4.5.3(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)
|
||||
'@vintl/vintl':
|
||||
specifier: ^4.4.1
|
||||
version: 4.4.1(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4))
|
||||
@ -2476,9 +2482,6 @@ packages:
|
||||
'@types/eslint-scope@3.7.7':
|
||||
resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==}
|
||||
|
||||
'@types/eslint@9.6.0':
|
||||
resolution: {integrity: sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==}
|
||||
|
||||
'@types/eslint@9.6.1':
|
||||
resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==}
|
||||
|
||||
@ -3606,8 +3609,8 @@ packages:
|
||||
resolution: {integrity: sha512-onMB0OkDjkXunhdW9htFjEhqrD54+M94i6ackoUkjHKbRnXdyEyKRelp4nJ1kAz32+s27jP1FsebpJCVl0BsvA==}
|
||||
engines: {node: '>=18.0'}
|
||||
|
||||
cronstrue@2.52.0:
|
||||
resolution: {integrity: sha512-NKgHbWkSZXJUcaBHSsyzC8eegD6bBd4O0oCI6XMIJ+y4Bq3v4w7sY3wfWoKPuVlq9pQHRB6od0lmKpIqi8TlKA==}
|
||||
cronstrue@2.61.0:
|
||||
resolution: {integrity: sha512-ootN5bvXbIQI9rW94+QsXN5eROtXWwew6NkdGxIRpS/UFWRggL0G5Al7a9GTBFEsuvVhJ2K3CntIIVt7L2ILhA==}
|
||||
hasBin: true
|
||||
|
||||
cross-spawn@6.0.6:
|
||||
@ -8148,12 +8151,12 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@astrojs/mdx@4.1.0(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1))':
|
||||
'@astrojs/mdx@4.1.0(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1))':
|
||||
dependencies:
|
||||
'@astrojs/markdown-remark': 6.2.0
|
||||
'@mdx-js/mdx': 3.1.0(acorn@8.14.0)
|
||||
acorn: 8.14.0
|
||||
astro: 5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1)
|
||||
astro: 5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1)
|
||||
es-module-lexer: 1.6.0
|
||||
estree-util-visit: 2.0.0
|
||||
hast-util-to-html: 9.0.5
|
||||
@ -8177,16 +8180,16 @@ snapshots:
|
||||
stream-replace-string: 2.0.0
|
||||
zod: 3.23.8
|
||||
|
||||
'@astrojs/starlight@0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1))':
|
||||
'@astrojs/starlight@0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1))':
|
||||
dependencies:
|
||||
'@astrojs/mdx': 4.1.0(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1))
|
||||
'@astrojs/mdx': 4.1.0(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1))
|
||||
'@astrojs/sitemap': 3.2.1
|
||||
'@pagefind/default-ui': 1.3.0
|
||||
'@types/hast': 3.0.4
|
||||
'@types/js-yaml': 4.0.9
|
||||
'@types/mdast': 4.0.4
|
||||
astro: 5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1)
|
||||
astro-expressive-code: 0.40.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1))
|
||||
astro: 5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1)
|
||||
astro-expressive-code: 0.40.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1))
|
||||
bcp-47: 2.1.0
|
||||
hast-util-from-html: 2.0.2
|
||||
hast-util-select: 6.0.2
|
||||
@ -9267,12 +9270,12 @@ snapshots:
|
||||
|
||||
'@nuxt/devalue@2.0.2': {}
|
||||
|
||||
'@nuxt/devtools-kit@1.6.3(magicast@0.3.5)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))':
|
||||
'@nuxt/devtools-kit@1.6.3(magicast@0.3.5)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))':
|
||||
dependencies:
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1)
|
||||
'@nuxt/schema': 3.14.1592(magicast@0.3.5)(rollup@4.28.1)
|
||||
execa: 7.2.0
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
- rollup
|
||||
@ -9291,17 +9294,17 @@ snapshots:
|
||||
rc9: 2.1.2
|
||||
semver: 7.7.1
|
||||
|
||||
'@nuxt/devtools@1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))':
|
||||
'@nuxt/devtools@1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))':
|
||||
dependencies:
|
||||
'@antfu/utils': 0.7.10
|
||||
'@nuxt/devtools-kit': 1.6.3(magicast@0.3.5)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))
|
||||
'@nuxt/devtools-kit': 1.6.3(magicast@0.3.5)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))
|
||||
'@nuxt/devtools-wizard': 1.6.3
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1)
|
||||
'@vue/devtools-core': 7.6.4(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))
|
||||
'@vue/devtools-core': 7.6.4(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))
|
||||
'@vue/devtools-kit': 7.6.4
|
||||
birpc: 0.2.19
|
||||
consola: 3.2.3
|
||||
cronstrue: 2.52.0
|
||||
cronstrue: 2.61.0
|
||||
destr: 2.0.3
|
||||
error-stack-parser-es: 0.1.5
|
||||
execa: 7.2.0
|
||||
@ -9326,9 +9329,9 @@ snapshots:
|
||||
sirv: 3.0.0
|
||||
tinyglobby: 0.2.10
|
||||
unimport: 3.14.4(rollup@4.28.1)
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)
|
||||
vite-plugin-inspect: 0.8.9(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.28.1))(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))
|
||||
vite-plugin-vue-inspector: 5.1.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)
|
||||
vite-plugin-inspect: 0.8.9(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.28.1))(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))
|
||||
vite-plugin-vue-inspector: 5.1.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))
|
||||
which: 3.0.1
|
||||
ws: 8.18.0
|
||||
transitivePeerDependencies:
|
||||
@ -9370,9 +9373,9 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
'@nuxt/kit@3.14.1592':
|
||||
'@nuxt/kit@3.14.1592(magicast@0.3.5)':
|
||||
dependencies:
|
||||
'@nuxt/schema': 3.14.1592
|
||||
'@nuxt/schema': 3.14.1592(magicast@0.3.5)
|
||||
c12: 2.0.1(magicast@0.3.5)
|
||||
consola: 3.2.3
|
||||
defu: 6.1.4
|
||||
@ -9398,6 +9401,34 @@ snapshots:
|
||||
- supports-color
|
||||
optional: true
|
||||
|
||||
'@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@3.29.4)':
|
||||
dependencies:
|
||||
'@nuxt/schema': 3.14.1592(magicast@0.3.5)(rollup@3.29.4)
|
||||
c12: 2.0.1(magicast@0.3.5)
|
||||
consola: 3.2.3
|
||||
defu: 6.1.4
|
||||
destr: 2.0.3
|
||||
globby: 14.0.2
|
||||
hash-sum: 2.0.0
|
||||
ignore: 6.0.2
|
||||
jiti: 2.4.1
|
||||
klona: 2.0.6
|
||||
knitwork: 1.1.0
|
||||
mlly: 1.7.3
|
||||
pathe: 1.1.2
|
||||
pkg-types: 1.2.1
|
||||
scule: 1.3.0
|
||||
semver: 7.7.1
|
||||
ufo: 1.5.4
|
||||
unctx: 2.3.1
|
||||
unimport: 3.14.4(rollup@3.29.4)
|
||||
untyped: 1.5.1
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
- rollup
|
||||
- supports-color
|
||||
optional: true
|
||||
|
||||
'@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.28.1)':
|
||||
dependencies:
|
||||
'@nuxt/schema': 3.14.1592(magicast@0.3.5)(rollup@4.28.1)
|
||||
@ -9425,35 +9456,7 @@ snapshots:
|
||||
- rollup
|
||||
- supports-color
|
||||
|
||||
'@nuxt/kit@3.14.1592(rollup@3.29.4)':
|
||||
dependencies:
|
||||
'@nuxt/schema': 3.14.1592(rollup@3.29.4)
|
||||
c12: 2.0.1(magicast@0.3.5)
|
||||
consola: 3.2.3
|
||||
defu: 6.1.4
|
||||
destr: 2.0.3
|
||||
globby: 14.0.2
|
||||
hash-sum: 2.0.0
|
||||
ignore: 6.0.2
|
||||
jiti: 2.4.1
|
||||
klona: 2.0.6
|
||||
knitwork: 1.1.0
|
||||
mlly: 1.7.3
|
||||
pathe: 1.1.2
|
||||
pkg-types: 1.2.1
|
||||
scule: 1.3.0
|
||||
semver: 7.7.1
|
||||
ufo: 1.5.4
|
||||
unctx: 2.3.1
|
||||
unimport: 3.14.4(rollup@3.29.4)
|
||||
untyped: 1.5.1
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
- rollup
|
||||
- supports-color
|
||||
optional: true
|
||||
|
||||
'@nuxt/schema@3.14.1592':
|
||||
'@nuxt/schema@3.14.1592(magicast@0.3.5)':
|
||||
dependencies:
|
||||
c12: 2.0.1(magicast@0.3.5)
|
||||
compatx: 0.1.8
|
||||
@ -9474,6 +9477,27 @@ snapshots:
|
||||
- supports-color
|
||||
optional: true
|
||||
|
||||
'@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@3.29.4)':
|
||||
dependencies:
|
||||
c12: 2.0.1(magicast@0.3.5)
|
||||
compatx: 0.1.8
|
||||
consola: 3.2.3
|
||||
defu: 6.1.4
|
||||
hookable: 5.5.3
|
||||
pathe: 1.1.2
|
||||
pkg-types: 1.2.1
|
||||
scule: 1.3.0
|
||||
std-env: 3.8.0
|
||||
ufo: 1.5.4
|
||||
uncrypto: 0.1.3
|
||||
unimport: 3.14.4(rollup@3.29.4)
|
||||
untyped: 1.5.1
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
- rollup
|
||||
- supports-color
|
||||
optional: true
|
||||
|
||||
'@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.28.1)':
|
||||
dependencies:
|
||||
c12: 2.0.1(magicast@0.3.5)
|
||||
@ -9494,27 +9518,6 @@ snapshots:
|
||||
- rollup
|
||||
- supports-color
|
||||
|
||||
'@nuxt/schema@3.14.1592(rollup@3.29.4)':
|
||||
dependencies:
|
||||
c12: 2.0.1(magicast@0.3.5)
|
||||
compatx: 0.1.8
|
||||
consola: 3.2.3
|
||||
defu: 6.1.4
|
||||
hookable: 5.5.3
|
||||
pathe: 1.1.2
|
||||
pkg-types: 1.2.1
|
||||
scule: 1.3.0
|
||||
std-env: 3.8.0
|
||||
ufo: 1.5.4
|
||||
uncrypto: 0.1.3
|
||||
unimport: 3.14.4(rollup@3.29.4)
|
||||
untyped: 1.5.1
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
- rollup
|
||||
- supports-color
|
||||
optional: true
|
||||
|
||||
'@nuxt/telemetry@2.6.0(magicast@0.3.5)(rollup@4.28.1)':
|
||||
dependencies:
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1)
|
||||
@ -9540,12 +9543,12 @@ snapshots:
|
||||
- rollup
|
||||
- supports-color
|
||||
|
||||
'@nuxt/vite-builder@3.14.1592(@types/node@20.14.11)(eslint@8.57.0)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.31.6)(typescript@5.5.4)(vue-tsc@2.1.6(typescript@5.5.4))(vue@3.5.13(typescript@5.5.4))':
|
||||
'@nuxt/vite-builder@3.14.1592(@types/node@20.14.11)(eslint@8.57.0)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.42.0)(typescript@5.5.4)(vue-tsc@2.1.6(typescript@5.5.4))(vue@3.5.13(typescript@5.5.4))':
|
||||
dependencies:
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1)
|
||||
'@rollup/plugin-replace': 6.0.1(rollup@4.28.1)
|
||||
'@vitejs/plugin-vue': 5.2.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))
|
||||
'@vitejs/plugin-vue-jsx': 4.1.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))
|
||||
'@vitejs/plugin-vue': 5.2.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))
|
||||
'@vitejs/plugin-vue-jsx': 4.1.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))
|
||||
autoprefixer: 10.4.20(postcss@8.4.49)
|
||||
clear: 0.1.0
|
||||
consola: 3.2.3
|
||||
@ -9572,9 +9575,9 @@ snapshots:
|
||||
ufo: 1.5.4
|
||||
unenv: 1.10.0
|
||||
unplugin: 1.16.0
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)
|
||||
vite-node: 2.1.8(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)
|
||||
vite-plugin-checker: 0.8.0(eslint@8.57.0)(optionator@0.9.4)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue-tsc@2.1.6(typescript@5.5.4))
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)
|
||||
vite-node: 2.1.8(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)
|
||||
vite-plugin-checker: 0.8.0(eslint@8.57.0)(optionator@0.9.4)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue-tsc@2.1.6(typescript@5.5.4))
|
||||
vue: 3.5.13(typescript@5.5.4)
|
||||
vue-bundle-renderer: 2.1.1
|
||||
transitivePeerDependencies:
|
||||
@ -9601,7 +9604,7 @@ snapshots:
|
||||
|
||||
'@nuxtjs/eslint-config-typescript@12.1.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4)':
|
||||
dependencies:
|
||||
'@nuxtjs/eslint-config': 12.0.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@9.13.0(jiti@2.4.1)))(eslint@9.13.0(jiti@2.4.1))
|
||||
'@nuxtjs/eslint-config': 12.0.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.1))
|
||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4)
|
||||
eslint: 9.13.0(jiti@2.4.1)
|
||||
@ -9614,10 +9617,10 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
'@nuxtjs/eslint-config@12.0.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@9.13.0(jiti@2.4.1)))(eslint@9.13.0(jiti@2.4.1))':
|
||||
'@nuxtjs/eslint-config@12.0.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.1))':
|
||||
dependencies:
|
||||
eslint: 9.13.0(jiti@2.4.1)
|
||||
eslint-config-standard: 17.1.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.1)))(eslint-plugin-n@15.7.0(eslint@9.13.0(jiti@2.4.1)))(eslint-plugin-promise@6.4.0(eslint@9.13.0(jiti@2.4.1)))(eslint@9.13.0(jiti@2.4.1))
|
||||
eslint-config-standard: 17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0(eslint@9.13.0(jiti@2.4.1)))(eslint-plugin-promise@6.4.0(eslint@9.13.0(jiti@2.4.1)))(eslint@9.13.0(jiti@2.4.1))
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.1))
|
||||
eslint-plugin-n: 15.7.0(eslint@9.13.0(jiti@2.4.1))
|
||||
eslint-plugin-node: 11.1.0(eslint@9.13.0(jiti@2.4.1))
|
||||
@ -10182,12 +10185,6 @@ snapshots:
|
||||
'@types/estree': 1.0.8
|
||||
optional: true
|
||||
|
||||
'@types/eslint@9.6.0':
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/json-schema': 7.0.15
|
||||
optional: true
|
||||
|
||||
'@types/eslint@9.6.1':
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
@ -10597,12 +10594,12 @@ snapshots:
|
||||
'@formatjs/intl': 2.10.4(typescript@5.5.4)
|
||||
intl-messageformat: 10.5.14
|
||||
|
||||
'@vintl/nuxt@1.9.2(@vue/compiler-core@3.5.13)(magicast@0.3.5)(rollup@4.28.1)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)':
|
||||
'@vintl/nuxt@1.9.2(@vue/compiler-core@3.5.13)(magicast@0.3.5)(rollup@4.28.1)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)':
|
||||
dependencies:
|
||||
'@formatjs/intl': 2.10.4(typescript@5.5.4)
|
||||
'@formatjs/intl-localematcher': 0.5.4
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1)
|
||||
'@vintl/unplugin': 2.0.0(@vue/compiler-core@3.5.13)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)
|
||||
'@vintl/unplugin': 2.0.0(@vue/compiler-core@3.5.13)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)
|
||||
'@vintl/vintl': 4.4.1(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4))
|
||||
astring: 1.8.6
|
||||
consola: 3.2.3
|
||||
@ -10629,7 +10626,7 @@ snapshots:
|
||||
- vue
|
||||
- webpack
|
||||
|
||||
'@vintl/unplugin@1.5.2(@vue/compiler-core@3.5.13)(rollup@3.29.4)(vite@4.5.3(@types/node@22.4.1))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)':
|
||||
'@vintl/unplugin@1.5.2(@vue/compiler-core@3.5.13)(rollup@3.29.4)(vite@4.5.3(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)':
|
||||
dependencies:
|
||||
'@formatjs/cli-lib': 6.4.2(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.5.4))
|
||||
'@formatjs/icu-messageformat-parser': 2.7.8
|
||||
@ -10640,7 +10637,7 @@ snapshots:
|
||||
unplugin: 1.16.0
|
||||
optionalDependencies:
|
||||
rollup: 3.29.4
|
||||
vite: 4.5.3(@types/node@22.4.1)
|
||||
vite: 4.5.3(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0)
|
||||
webpack: 5.92.1
|
||||
transitivePeerDependencies:
|
||||
- '@glimmer/env'
|
||||
@ -10653,7 +10650,7 @@ snapshots:
|
||||
- ts-jest
|
||||
- vue
|
||||
|
||||
'@vintl/unplugin@2.0.0(@vue/compiler-core@3.5.13)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)':
|
||||
'@vintl/unplugin@2.0.0(@vue/compiler-core@3.5.13)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)':
|
||||
dependencies:
|
||||
'@formatjs/cli-lib': 6.4.2(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.5.4))
|
||||
'@formatjs/icu-messageformat-parser': 2.7.8
|
||||
@ -10664,7 +10661,7 @@ snapshots:
|
||||
unplugin: 1.16.0
|
||||
optionalDependencies:
|
||||
rollup: 4.28.1
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)
|
||||
webpack: 5.92.1
|
||||
transitivePeerDependencies:
|
||||
- '@glimmer/env'
|
||||
@ -10688,24 +10685,24 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
'@vitejs/plugin-vue-jsx@4.1.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))':
|
||||
'@vitejs/plugin-vue-jsx@4.1.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))':
|
||||
dependencies:
|
||||
'@babel/core': 7.26.0
|
||||
'@babel/plugin-transform-typescript': 7.26.3(@babel/core@7.26.0)
|
||||
'@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.26.0)
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)
|
||||
vue: 3.5.13(typescript@5.5.4)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@vitejs/plugin-vue@5.2.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))':
|
||||
'@vitejs/plugin-vue@5.2.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))':
|
||||
dependencies:
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)
|
||||
vue: 3.5.13(typescript@5.5.4)
|
||||
|
||||
'@vitejs/plugin-vue@5.2.1(vite@5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))':
|
||||
'@vitejs/plugin-vue@5.2.1(vite@5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))':
|
||||
dependencies:
|
||||
vite: 5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.31.6)
|
||||
vite: 5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0)
|
||||
vue: 3.5.13(typescript@5.5.4)
|
||||
|
||||
'@volar/kit@2.4.11(typescript@5.8.2)':
|
||||
@ -10850,14 +10847,14 @@ snapshots:
|
||||
|
||||
'@vue/devtools-api@6.6.4': {}
|
||||
|
||||
'@vue/devtools-core@7.6.4(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))':
|
||||
'@vue/devtools-core@7.6.4(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))':
|
||||
dependencies:
|
||||
'@vue/devtools-kit': 7.6.4
|
||||
'@vue/devtools-shared': 7.6.7
|
||||
mitt: 3.0.1
|
||||
nanoid: 3.3.7
|
||||
pathe: 1.1.2
|
||||
vite-hot-client: 0.2.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))
|
||||
vite-hot-client: 0.2.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))
|
||||
vue: 3.5.13(typescript@5.5.4)
|
||||
transitivePeerDependencies:
|
||||
- vite
|
||||
@ -11286,12 +11283,12 @@ snapshots:
|
||||
|
||||
astring@1.8.6: {}
|
||||
|
||||
astro-expressive-code@0.40.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1)):
|
||||
astro-expressive-code@0.40.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1)):
|
||||
dependencies:
|
||||
astro: 5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1)
|
||||
astro: 5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1)
|
||||
rehype-expressive-code: 0.40.2
|
||||
|
||||
astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1):
|
||||
astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1):
|
||||
dependencies:
|
||||
'@astrojs/compiler': 2.10.4
|
||||
'@astrojs/internal-helpers': 0.6.0
|
||||
@ -11343,8 +11340,8 @@ snapshots:
|
||||
unist-util-visit: 5.0.0
|
||||
unstorage: 1.15.0(db0@0.2.1)
|
||||
vfile: 6.0.3
|
||||
vite: 6.2.0(@types/node@22.4.1)(jiti@2.4.1)(sass@1.77.6)(terser@5.31.6)(yaml@2.6.1)
|
||||
vitefu: 1.0.6(vite@6.2.0(@types/node@22.4.1)(jiti@2.4.1)(sass@1.77.6)(terser@5.31.6)(yaml@2.6.1))
|
||||
vite: 6.2.0(@types/node@22.4.1)(jiti@2.4.1)(sass@1.77.6)(terser@5.42.0)(yaml@2.6.1)
|
||||
vitefu: 1.0.6(vite@6.2.0(@types/node@22.4.1)(jiti@2.4.1)(sass@1.77.6)(terser@5.42.0)(yaml@2.6.1))
|
||||
which-pm: 3.0.1
|
||||
xxhash-wasm: 1.1.0
|
||||
yargs-parser: 21.1.1
|
||||
@ -11725,7 +11722,7 @@ snapshots:
|
||||
|
||||
croner@9.0.0: {}
|
||||
|
||||
cronstrue@2.52.0: {}
|
||||
cronstrue@2.61.0: {}
|
||||
|
||||
cross-spawn@6.0.6:
|
||||
dependencies:
|
||||
@ -12276,10 +12273,10 @@ snapshots:
|
||||
dependencies:
|
||||
eslint: 9.13.0(jiti@2.4.1)
|
||||
|
||||
eslint-config-standard@17.1.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.1)))(eslint-plugin-n@15.7.0(eslint@9.13.0(jiti@2.4.1)))(eslint-plugin-promise@6.4.0(eslint@9.13.0(jiti@2.4.1)))(eslint@9.13.0(jiti@2.4.1)):
|
||||
eslint-config-standard@17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0(eslint@9.13.0(jiti@2.4.1)))(eslint-plugin-promise@6.4.0(eslint@9.13.0(jiti@2.4.1)))(eslint@9.13.0(jiti@2.4.1)):
|
||||
dependencies:
|
||||
eslint: 9.13.0(jiti@2.4.1)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.1))
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.1))
|
||||
eslint-plugin-n: 15.7.0(eslint@9.13.0(jiti@2.4.1))
|
||||
eslint-plugin-promise: 6.4.0(eslint@9.13.0(jiti@2.4.1))
|
||||
|
||||
@ -12305,7 +12302,7 @@ snapshots:
|
||||
debug: 4.4.0(supports-color@9.4.0)
|
||||
enhanced-resolve: 5.17.1
|
||||
eslint: 9.13.0(jiti@2.4.1)
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@9.13.0(jiti@2.4.1)))(eslint@9.13.0(jiti@2.4.1))
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.1))
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.1))
|
||||
fast-glob: 3.3.2
|
||||
get-tsconfig: 4.7.5
|
||||
@ -12317,7 +12314,7 @@ snapshots:
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
|
||||
eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@9.13.0(jiti@2.4.1)))(eslint@9.13.0(jiti@2.4.1)):
|
||||
eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.1)):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
@ -12460,14 +12457,14 @@ snapshots:
|
||||
resolve: 1.22.8
|
||||
semver: 6.3.1
|
||||
|
||||
eslint-plugin-prettier@5.2.1(@types/eslint@9.6.0)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.4.1)))(eslint@9.13.0(jiti@2.4.1))(prettier@3.3.2):
|
||||
eslint-plugin-prettier@5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.4.1)))(eslint@9.13.0(jiti@2.4.1))(prettier@3.3.2):
|
||||
dependencies:
|
||||
eslint: 9.13.0(jiti@2.4.1)
|
||||
prettier: 3.3.2
|
||||
prettier-linter-helpers: 1.0.0
|
||||
synckit: 0.9.1
|
||||
optionalDependencies:
|
||||
'@types/eslint': 9.6.0
|
||||
'@types/eslint': 9.6.1
|
||||
eslint-config-prettier: 9.1.0(eslint@9.13.0(jiti@2.4.1))
|
||||
|
||||
eslint-plugin-promise@6.4.0(eslint@9.13.0(jiti@2.4.1)):
|
||||
@ -12894,6 +12891,14 @@ snapshots:
|
||||
|
||||
flattie@1.1.1: {}
|
||||
|
||||
floating-vue@5.2.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@3.29.4))(vue@3.5.13(typescript@5.5.4)):
|
||||
dependencies:
|
||||
'@floating-ui/dom': 1.1.1
|
||||
vue: 3.5.13(typescript@5.5.4)
|
||||
vue-resize: 2.0.0-alpha.1(vue@3.5.13(typescript@5.5.4))
|
||||
optionalDependencies:
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@3.29.4)
|
||||
|
||||
floating-vue@5.2.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.28.1))(vue@3.5.13(typescript@5.5.4)):
|
||||
dependencies:
|
||||
'@floating-ui/dom': 1.1.1
|
||||
@ -12902,21 +12907,13 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1)
|
||||
|
||||
floating-vue@5.2.2(@nuxt/kit@3.14.1592(rollup@3.29.4))(vue@3.5.13(typescript@5.5.4)):
|
||||
floating-vue@5.2.2(@nuxt/kit@3.14.1592(magicast@0.3.5))(vue@3.5.13(typescript@5.5.4)):
|
||||
dependencies:
|
||||
'@floating-ui/dom': 1.1.1
|
||||
vue: 3.5.13(typescript@5.5.4)
|
||||
vue-resize: 2.0.0-alpha.1(vue@3.5.13(typescript@5.5.4))
|
||||
optionalDependencies:
|
||||
'@nuxt/kit': 3.14.1592(rollup@3.29.4)
|
||||
|
||||
floating-vue@5.2.2(@nuxt/kit@3.14.1592)(vue@3.5.13(typescript@5.5.4)):
|
||||
dependencies:
|
||||
'@floating-ui/dom': 1.1.1
|
||||
vue: 3.5.13(typescript@5.5.4)
|
||||
vue-resize: 2.0.0-alpha.1(vue@3.5.13(typescript@5.5.4))
|
||||
optionalDependencies:
|
||||
'@nuxt/kit': 3.14.1592
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)
|
||||
|
||||
for-each@0.3.3:
|
||||
dependencies:
|
||||
@ -13686,7 +13683,7 @@ snapshots:
|
||||
|
||||
jest-worker@27.5.1:
|
||||
dependencies:
|
||||
'@types/node': 22.4.1
|
||||
'@types/node': 20.14.11
|
||||
merge-stream: 2.0.0
|
||||
supports-color: 8.1.1
|
||||
optional: true
|
||||
@ -14664,14 +14661,14 @@ snapshots:
|
||||
|
||||
nuxi@3.16.0: {}
|
||||
|
||||
nuxt@3.14.1592(@parcel/watcher@2.4.1)(@types/node@20.14.11)(eslint@8.57.0)(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.31.6)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue-tsc@2.1.6(typescript@5.5.4)):
|
||||
nuxt@3.14.1592(@parcel/watcher@2.4.1)(@types/node@20.14.11)(eslint@8.57.0)(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.42.0)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue-tsc@2.1.6(typescript@5.5.4)):
|
||||
dependencies:
|
||||
'@nuxt/devalue': 2.0.2
|
||||
'@nuxt/devtools': 1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue@3.5.13(typescript@5.5.4))
|
||||
'@nuxt/devtools': 1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1)
|
||||
'@nuxt/schema': 3.14.1592(magicast@0.3.5)(rollup@4.28.1)
|
||||
'@nuxt/telemetry': 2.6.0(magicast@0.3.5)(rollup@4.28.1)
|
||||
'@nuxt/vite-builder': 3.14.1592(@types/node@20.14.11)(eslint@8.57.0)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.31.6)(typescript@5.5.4)(vue-tsc@2.1.6(typescript@5.5.4))(vue@3.5.13(typescript@5.5.4))
|
||||
'@nuxt/vite-builder': 3.14.1592(@types/node@20.14.11)(eslint@8.57.0)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.42.0)(typescript@5.5.4)(vue-tsc@2.1.6(typescript@5.5.4))(vue@3.5.13(typescript@5.5.4))
|
||||
'@unhead/dom': 1.11.13
|
||||
'@unhead/shared': 1.11.13
|
||||
'@unhead/ssr': 1.11.13
|
||||
@ -16008,12 +16005,12 @@ snapshots:
|
||||
|
||||
standard-as-callback@2.1.0: {}
|
||||
|
||||
starlight-openapi@0.14.0(@astrojs/markdown-remark@6.2.0)(@astrojs/starlight@0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1)))(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1))(openapi-types@12.1.3):
|
||||
starlight-openapi@0.14.0(@astrojs/markdown-remark@6.2.0)(@astrojs/starlight@0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1)))(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1))(openapi-types@12.1.3):
|
||||
dependencies:
|
||||
'@astrojs/markdown-remark': 6.2.0
|
||||
'@astrojs/starlight': 0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1))
|
||||
'@astrojs/starlight': 0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1))
|
||||
'@readme/openapi-parser': 2.5.0(openapi-types@12.1.3)
|
||||
astro: 5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.31.6)(typescript@5.8.2)(yaml@2.6.1)
|
||||
astro: 5.4.1(@types/node@22.4.1)(db0@0.2.1)(jiti@2.4.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.6.1)
|
||||
github-slugger: 2.0.0
|
||||
url-template: 3.1.1
|
||||
transitivePeerDependencies:
|
||||
@ -16484,7 +16481,7 @@ snapshots:
|
||||
|
||||
unimport@3.14.4:
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.1.3(rollup@3.29.4)
|
||||
'@rollup/pluginutils': 5.1.3(rollup@4.28.1)
|
||||
acorn: 8.14.0
|
||||
escape-string-regexp: 5.0.0
|
||||
estree-walker: 3.0.3
|
||||
@ -16723,17 +16720,17 @@ snapshots:
|
||||
'@types/unist': 3.0.3
|
||||
vfile-message: 4.0.2
|
||||
|
||||
vite-hot-client@0.2.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)):
|
||||
vite-hot-client@0.2.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)):
|
||||
dependencies:
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)
|
||||
|
||||
vite-node@2.1.8(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6):
|
||||
vite-node@2.1.8(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.4.0(supports-color@9.4.0)
|
||||
es-module-lexer: 1.5.4
|
||||
pathe: 1.1.2
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- less
|
||||
@ -16745,7 +16742,7 @@ snapshots:
|
||||
- supports-color
|
||||
- terser
|
||||
|
||||
vite-plugin-checker@0.8.0(eslint@8.57.0)(optionator@0.9.4)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6))(vue-tsc@2.1.6(typescript@5.5.4)):
|
||||
vite-plugin-checker@0.8.0(eslint@8.57.0)(optionator@0.9.4)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue-tsc@2.1.6(typescript@5.5.4)):
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.26.2
|
||||
ansi-escapes: 4.3.2
|
||||
@ -16757,7 +16754,7 @@ snapshots:
|
||||
npm-run-path: 4.0.1
|
||||
strip-ansi: 6.0.1
|
||||
tiny-invariant: 1.3.3
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)
|
||||
vscode-languageclient: 7.0.0
|
||||
vscode-languageserver: 7.0.0
|
||||
vscode-languageserver-textdocument: 1.0.12
|
||||
@ -16768,7 +16765,7 @@ snapshots:
|
||||
typescript: 5.5.4
|
||||
vue-tsc: 2.1.6(typescript@5.5.4)
|
||||
|
||||
vite-plugin-inspect@0.8.9(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.28.1))(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)):
|
||||
vite-plugin-inspect@0.8.9(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.28.1))(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)):
|
||||
dependencies:
|
||||
'@antfu/utils': 0.7.10
|
||||
'@rollup/pluginutils': 5.1.3(rollup@4.28.1)
|
||||
@ -16779,14 +16776,14 @@ snapshots:
|
||||
perfect-debounce: 1.0.0
|
||||
picocolors: 1.1.1
|
||||
sirv: 3.0.0
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)
|
||||
optionalDependencies:
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1)
|
||||
transitivePeerDependencies:
|
||||
- rollup
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-inspector@5.1.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)):
|
||||
vite-plugin-vue-inspector@5.1.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)):
|
||||
dependencies:
|
||||
'@babel/core': 7.26.0
|
||||
'@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.26.0)
|
||||
@ -16797,7 +16794,7 @@ snapshots:
|
||||
'@vue/compiler-dom': 3.5.13
|
||||
kolorist: 1.8.0
|
||||
magic-string: 0.30.14
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6)
|
||||
vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@ -16806,7 +16803,7 @@ snapshots:
|
||||
svgo: 3.3.2
|
||||
vue: 3.5.13(typescript@5.5.4)
|
||||
|
||||
vite@4.5.3(@types/node@22.4.1):
|
||||
vite@4.5.3(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0):
|
||||
dependencies:
|
||||
esbuild: 0.18.20
|
||||
postcss: 8.5.5
|
||||
@ -16814,9 +16811,11 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/node': 22.4.1
|
||||
fsevents: 2.3.3
|
||||
sass: 1.77.6
|
||||
terser: 5.42.0
|
||||
optional: true
|
||||
|
||||
vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.31.6):
|
||||
vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0):
|
||||
dependencies:
|
||||
esbuild: 0.21.5
|
||||
postcss: 8.4.49
|
||||
@ -16825,9 +16824,9 @@ snapshots:
|
||||
'@types/node': 20.14.11
|
||||
fsevents: 2.3.3
|
||||
sass: 1.77.6
|
||||
terser: 5.31.6
|
||||
terser: 5.42.0
|
||||
|
||||
vite@5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.31.6):
|
||||
vite@5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0):
|
||||
dependencies:
|
||||
esbuild: 0.21.5
|
||||
postcss: 8.4.49
|
||||
@ -16836,9 +16835,9 @@ snapshots:
|
||||
'@types/node': 22.4.1
|
||||
fsevents: 2.3.3
|
||||
sass: 1.77.6
|
||||
terser: 5.31.6
|
||||
terser: 5.42.0
|
||||
|
||||
vite@6.2.0(@types/node@22.4.1)(jiti@2.4.1)(sass@1.77.6)(terser@5.31.6)(yaml@2.6.1):
|
||||
vite@6.2.0(@types/node@22.4.1)(jiti@2.4.1)(sass@1.77.6)(terser@5.42.0)(yaml@2.6.1):
|
||||
dependencies:
|
||||
esbuild: 0.25.0
|
||||
postcss: 8.5.3
|
||||
@ -16848,12 +16847,12 @@ snapshots:
|
||||
fsevents: 2.3.3
|
||||
jiti: 2.4.1
|
||||
sass: 1.77.6
|
||||
terser: 5.31.6
|
||||
terser: 5.42.0
|
||||
yaml: 2.6.1
|
||||
|
||||
vitefu@1.0.6(vite@6.2.0(@types/node@22.4.1)(jiti@2.4.1)(sass@1.77.6)(terser@5.31.6)(yaml@2.6.1)):
|
||||
vitefu@1.0.6(vite@6.2.0(@types/node@22.4.1)(jiti@2.4.1)(sass@1.77.6)(terser@5.42.0)(yaml@2.6.1)):
|
||||
optionalDependencies:
|
||||
vite: 6.2.0(@types/node@22.4.1)(jiti@2.4.1)(sass@1.77.6)(terser@5.31.6)(yaml@2.6.1)
|
||||
vite: 6.2.0(@types/node@22.4.1)(jiti@2.4.1)(sass@1.77.6)(terser@5.42.0)(yaml@2.6.1)
|
||||
|
||||
volar-service-css@0.0.62(@volar/language-service@2.4.11):
|
||||
dependencies:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user