Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0db0c656b2 | ||
|
|
22bbef9d8e | ||
|
|
4f2b8217f8 | ||
|
|
2fefd9da01 | ||
|
|
b3e9b3351b | ||
|
|
d48254fa57 | ||
|
|
b2fdab0418 | ||
|
|
e78dc86aa3 | ||
|
|
e70d804ab8 | ||
|
|
b7c3a48377 |
No files matched your search
@@ -13,6 +13,7 @@ import type { useForm } from "@homarr/form";
|
|||||||
import { useZodForm } from "@homarr/form";
|
import { useZodForm } from "@homarr/form";
|
||||||
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
|
import { showErrorNotification, showSuccessNotification } from "@homarr/notifications";
|
||||||
import { useScopedI18n } from "@homarr/translation/client";
|
import { useScopedI18n } from "@homarr/translation/client";
|
||||||
|
import { sanitizeRedirectionUrl } from "@homarr/validation/redirection-url";
|
||||||
import { userSignInSchema } from "@homarr/validation/user";
|
import { userSignInSchema } from "@homarr/validation/user";
|
||||||
|
|
||||||
type Provider = "credentials" | "ldap" | "oidc";
|
type Provider = "credentials" | "ldap" | "oidc";
|
||||||
@@ -70,7 +71,7 @@ export const LoginForm = ({ providers, oidcClientName, isOidcAutoLoginEnabled, c
|
|||||||
|
|
||||||
// Redirect to the callback URL if the response is defined and comes from a credentials provider (ldap or credentials). oidc is redirected automatically.
|
// Redirect to the callback URL if the response is defined and comes from a credentials provider (ldap or credentials). oidc is redirected automatically.
|
||||||
await revalidatePathActionAsync("/");
|
await revalidatePathActionAsync("/");
|
||||||
router.push(callbackUrl);
|
router.push(sanitizeRedirectionUrl(callbackUrl));
|
||||||
},
|
},
|
||||||
[t, router, callbackUrl],
|
[t, router, callbackUrl],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Card, Center, Stack, Text, Title } from "@mantine/core";
|
|||||||
import { env } from "@homarr/auth/env";
|
import { env } from "@homarr/auth/env";
|
||||||
import { auth } from "@homarr/auth/next";
|
import { auth } from "@homarr/auth/next";
|
||||||
import { getScopedI18n } from "@homarr/translation/server";
|
import { getScopedI18n } from "@homarr/translation/server";
|
||||||
|
import { sanitizeRedirectionUrl } from "@homarr/validation/redirection-url";
|
||||||
|
|
||||||
import { HomarrLogoWithTitle } from "~/components/layout/logo/homarr-logo";
|
import { HomarrLogoWithTitle } from "~/components/layout/logo/homarr-logo";
|
||||||
import { LoginForm } from "./_login-form";
|
import { LoginForm } from "./_login-form";
|
||||||
@@ -19,7 +20,7 @@ export default async function Login(props: LoginProps) {
|
|||||||
const session = await auth();
|
const session = await auth();
|
||||||
|
|
||||||
if (session) {
|
if (session) {
|
||||||
redirect(searchParams.callbackUrl ?? "/");
|
redirect(sanitizeRedirectionUrl(searchParams.callbackUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
const t = await getScopedI18n("user.page.login");
|
const t = await getScopedI18n("user.page.login");
|
||||||
|
|||||||
@@ -264,6 +264,5 @@ const usePreventLeaveWithDirty = (isDirty: boolean) => {
|
|||||||
window.removeEventListener("popstate", handlePopState);
|
window.removeEventListener("popstate", handlePopState);
|
||||||
window.removeEventListener("beforeunload", handleBeforeUnload);
|
window.removeEventListener("beforeunload", handleBeforeUnload);
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [isDirty]);
|
}, [isDirty]);
|
||||||
};
|
};
|
||||||
@@ -27,7 +27,6 @@ export const BoardReadyProvider = ({ children }: PropsWithChildren) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setReadySections((previous) => previous.filter((id) => board.sections.some((section) => section.id === id)));
|
setReadySections((previous) => previous.filter((id) => board.sections.some((section) => section.id === id)));
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [board.sections.length, setReadySections]);
|
}, [board.sections.length, setReadySections]);
|
||||||
|
|
||||||
const markAsReady = useCallback((id: string) => {
|
const markAsReady = useCallback((id: string) => {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { ApiKeysManagement } from "./components/api-keys";
|
|||||||
|
|
||||||
export async function generateMetadata() {
|
export async function generateMetadata() {
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
if (!session?.user || !session.user.permissions.includes("admin")) {
|
if (!session?.user.permissions.includes("admin")) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ export async function generateMetadata() {
|
|||||||
|
|
||||||
export default async function ApiPage() {
|
export default async function ApiPage() {
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
if (!session?.user || !session.user.permissions.includes("admin")) {
|
if (!session?.user.permissions.includes("admin")) {
|
||||||
notFound();
|
notFound();
|
||||||
}
|
}
|
||||||
const document = openApiDocument(extractBaseUrlFromHeaders(await headers()));
|
const document = openApiDocument(extractBaseUrlFromHeaders(await headers()));
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { LogContextProvider } from "./log-context";
|
|||||||
|
|
||||||
export async function generateMetadata() {
|
export async function generateMetadata() {
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
if (!session?.user || !session.user.permissions.includes("admin")) {
|
if (!session?.user.permissions.includes("admin")) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const t = await getScopedI18n("management");
|
const t = await getScopedI18n("management");
|
||||||
@@ -30,7 +30,7 @@ export async function generateMetadata() {
|
|||||||
|
|
||||||
export default async function LogsManagementPage() {
|
export default async function LogsManagementPage() {
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
if (!session?.user || !session.user.permissions.includes("other-view-logs")) {
|
if (!session?.user.permissions.includes("other-view-logs")) {
|
||||||
notFound();
|
notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ const executeHealthCheckSafelyAsync = async (
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
||||||
logger.error(new ErrorWithMetadata("Healthcheck failed", { name }, { cause: error }));
|
logger.error(new ErrorWithMetadata("Healthcheck failed", { name }, { cause: error }));
|
||||||
return {
|
return {
|
||||||
status: "unhealthy",
|
status: "unhealthy",
|
||||||
|
|||||||
@@ -117,7 +117,6 @@ const InnerContent = ({ item, ...dimensions }: InnerContentProps) => {
|
|||||||
when={
|
when={
|
||||||
widgetSupportsIntegrations &&
|
widgetSupportsIntegrations &&
|
||||||
item.integrationIds.length === 0 &&
|
item.integrationIds.length === 0 &&
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
||||||
(!("integrationsRequired" in definition) || definition.integrationsRequired !== false)
|
(!("integrationsRequired" in definition) || definition.integrationsRequired !== false)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -206,7 +206,6 @@ export const useGridstack = (section: Omit<Section, "items">, itemIds: string[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only run this effect when the section items change
|
// Only run this effect when the section items change
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [itemIds.length, columnCount]);
|
}, [itemIds.length, columnCount]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
"dotenv": "^17.3.1",
|
"dotenv": "^17.3.1",
|
||||||
"fastify": "^5.8.2",
|
"fastify": "^5.8.2",
|
||||||
"superjson": "2.2.6",
|
"superjson": "2.2.6",
|
||||||
"undici": "7.18.2"
|
"undici": "7.24.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
"octokit": "^5.0.5",
|
"octokit": "^5.0.5",
|
||||||
"react": "19.2.4",
|
"react": "19.2.4",
|
||||||
"react-dom": "19.2.4",
|
"react-dom": "19.2.4",
|
||||||
"undici": "7.18.2",
|
"undici": "7.24.5",
|
||||||
"zod": "^4.2.1",
|
"zod": "^4.2.1",
|
||||||
"zod-validation-error": "^5.0.0"
|
"zod-validation-error": "^5.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ export const integrationDefs = {
|
|||||||
name: "Nextcloud",
|
name: "Nextcloud",
|
||||||
secretKinds: [["username", "password"]],
|
secretKinds: [["username", "password"]],
|
||||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/nextcloud.svg",
|
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/nextcloud.svg",
|
||||||
category: ["calendar"],
|
category: ["calendar", "notifications"],
|
||||||
documentationUrl: createDocumentationLink("/docs/integrations/nextcloud"),
|
documentationUrl: createDocumentationLink("/docs/integrations/nextcloud"),
|
||||||
},
|
},
|
||||||
unifiController: {
|
unifiController: {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
"octokit": "^5.0.5",
|
"octokit": "^5.0.5",
|
||||||
"proxmox-api": "1.1.1",
|
"proxmox-api": "1.1.1",
|
||||||
"tsdav": "^2.1.8",
|
"tsdav": "^2.1.8",
|
||||||
"undici": "7.18.2",
|
"undici": "7.24.5",
|
||||||
"xml2js": "^0.6.2",
|
"xml2js": "^0.6.2",
|
||||||
"zod": "^4.2.1"
|
"zod": "^4.2.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import utc from "dayjs/plugin/utc";
|
|||||||
import type { RequestInit as NodeFetchRequestInit } from "node-fetch";
|
import type { RequestInit as NodeFetchRequestInit } from "node-fetch";
|
||||||
import * as ical from "node-ical";
|
import * as ical from "node-ical";
|
||||||
import { DAVClient } from "tsdav";
|
import { DAVClient } from "tsdav";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
import { createHttpsAgentAsync } from "@homarr/core/infrastructure/http";
|
import { ResponseError } from "@homarr/common/server";
|
||||||
|
import { createHttpsAgentAsync, fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http";
|
||||||
import { createLogger } from "@homarr/core/infrastructure/logs";
|
import { createLogger } from "@homarr/core/infrastructure/logs";
|
||||||
|
|
||||||
import { HandleIntegrationErrors } from "../base/errors/decorator";
|
import { HandleIntegrationErrors } from "../base/errors/decorator";
|
||||||
@@ -16,6 +18,21 @@ import { Integration } from "../base/integration";
|
|||||||
import type { TestingResult } from "../base/test-connection/test-connection-service";
|
import type { TestingResult } from "../base/test-connection/test-connection-service";
|
||||||
import type { ICalendarIntegration } from "../interfaces/calendar/calendar-integration";
|
import type { ICalendarIntegration } from "../interfaces/calendar/calendar-integration";
|
||||||
import type { CalendarEvent } from "../interfaces/calendar/calendar-types";
|
import type { CalendarEvent } from "../interfaces/calendar/calendar-types";
|
||||||
|
import type { Notification } from "../interfaces/notifications/notification-types";
|
||||||
|
import type { INotificationsIntegration } from "../interfaces/notifications/notifications-integration";
|
||||||
|
|
||||||
|
const notificationSchema = z.object({
|
||||||
|
ocs: z.object({
|
||||||
|
data: z.array(
|
||||||
|
z.object({
|
||||||
|
notification_id: z.number(),
|
||||||
|
datetime: z.string(),
|
||||||
|
subject: z.string(),
|
||||||
|
message: z.string(),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
const logger = createLogger({ module: "nextcloudIntegration" });
|
const logger = createLogger({ module: "nextcloudIntegration" });
|
||||||
|
|
||||||
@@ -23,7 +40,7 @@ dayjs.extend(utc);
|
|||||||
dayjs.extend(timezone);
|
dayjs.extend(timezone);
|
||||||
|
|
||||||
@HandleIntegrationErrors([integrationTsdavHttpErrorHandler])
|
@HandleIntegrationErrors([integrationTsdavHttpErrorHandler])
|
||||||
export class NextcloudIntegration extends Integration implements ICalendarIntegration {
|
export class NextcloudIntegration extends Integration implements ICalendarIntegration, INotificationsIntegration {
|
||||||
protected async testingAsync(input: IntegrationTestingInput): Promise<TestingResult> {
|
protected async testingAsync(input: IntegrationTestingInput): Promise<TestingResult> {
|
||||||
const client = await this.createCalendarClientAsync(await createHttpsAgentAsync(input.options));
|
const client = await this.createCalendarClientAsync(await createHttpsAgentAsync(input.options));
|
||||||
await client.login();
|
await client.login();
|
||||||
@@ -104,6 +121,29 @@ export class NextcloudIntegration extends Integration implements ICalendarIntegr
|
|||||||
.flat();
|
.flat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getNotificationsAsync(): Promise<Notification[]> {
|
||||||
|
const url = this.url("/ocs/v2.php/apps/notifications/api/v2/notifications", { format: "json" });
|
||||||
|
const response = await fetchWithTrustedCertificatesAsync(url, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Basic ${Buffer.from(
|
||||||
|
`${this.getSecretValue("username")}:${this.getSecretValue("password")}`,
|
||||||
|
).toString("base64")}`,
|
||||||
|
"OCS-APIRequest": "true",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) throw new ResponseError(response);
|
||||||
|
|
||||||
|
const json = notificationSchema.parse(await response.json());
|
||||||
|
|
||||||
|
return json.ocs.data.map((notification) => ({
|
||||||
|
id: String(notification.notification_id),
|
||||||
|
time: new Date(notification.datetime),
|
||||||
|
title: notification.subject,
|
||||||
|
body: notification.message,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
private async createCalendarClientAsync(agent?: Agent) {
|
private async createCalendarClientAsync(agent?: Agent) {
|
||||||
return new DAVClient({
|
return new DAVClient({
|
||||||
serverUrl: this.integration.url,
|
serverUrl: this.integration.url,
|
||||||
|
|||||||
@@ -57,10 +57,12 @@ export const AddBoardModal = createModal(({ actions }) => {
|
|||||||
{...form.getInputProps("name")}
|
{...form.getInputProps("name")}
|
||||||
description={
|
description={
|
||||||
boardNameStatus.description ? (
|
boardNameStatus.description ? (
|
||||||
<Group c={boardNameStatus.description.color} gap="xs" align="center">
|
<span>
|
||||||
{boardNameStatus.description.icon ? <boardNameStatus.description.icon size={16} /> : null}
|
<Group c={boardNameStatus.description.color} gap="xs" align="center">
|
||||||
<span>{boardNameStatus.description.label}</span>
|
{boardNameStatus.description.icon ? <boardNameStatus.description.icon size={16} /> : null}
|
||||||
</Group>
|
<span>{boardNameStatus.description.label}</span>
|
||||||
|
</Group>
|
||||||
|
</span>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ const optionMapping: OptionMapping = {
|
|||||||
allowMicrophone: (oldOptions) => oldOptions.allowMicrophone,
|
allowMicrophone: (oldOptions) => oldOptions.allowMicrophone,
|
||||||
allowGeolocation: (oldOptions) => oldOptions.allowGeolocation,
|
allowGeolocation: (oldOptions) => oldOptions.allowGeolocation,
|
||||||
allowScrolling: (oldOptions) => oldOptions.allowScrolling,
|
allowScrolling: (oldOptions) => oldOptions.allowScrolling,
|
||||||
|
allowModals: () => undefined,
|
||||||
},
|
},
|
||||||
video: {
|
video: {
|
||||||
feedUrl: (oldOptions) => oldOptions.FeedUrl,
|
feedUrl: (oldOptions) => oldOptions.FeedUrl,
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
"dayjs": "^1.11.20",
|
"dayjs": "^1.11.20",
|
||||||
"octokit": "^5.0.5",
|
"octokit": "^5.0.5",
|
||||||
"superjson": "2.2.6",
|
"superjson": "2.2.6",
|
||||||
"undici": "7.18.2",
|
"undici": "7.24.5",
|
||||||
"zod": "^4.2.1"
|
"zod": "^4.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ const createSpotlightContext = (displayName: string) => {
|
|||||||
context.unregisterItems(key);
|
context.unregisterItems(key);
|
||||||
};
|
};
|
||||||
// We ignore the results
|
// We ignore the results
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [...dependencyArray, key]);
|
}, [...dependencyArray, key]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1625,6 +1625,9 @@
|
|||||||
},
|
},
|
||||||
"allowGeolocation": {
|
"allowGeolocation": {
|
||||||
"label": "Allow geolocation"
|
"label": "Allow geolocation"
|
||||||
|
},
|
||||||
|
"allowModals": {
|
||||||
|
"label": "Allow modals"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
@@ -2033,7 +2036,6 @@
|
|||||||
"directStream": "Direct Stream"
|
"directStream": "Direct Stream"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"recentActivity": {
|
"recentActivity": {
|
||||||
"title": "Recent Activity",
|
"title": "Recent Activity",
|
||||||
"empty": "No recent activity",
|
"empty": "No recent activity",
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Sanitizes the URL from malicious payloads.
|
||||||
|
* Prevents open redirects such as //example.com/path
|
||||||
|
* and prevents XSS such as javascript:().
|
||||||
|
* Returns / as a default or when unsafe.
|
||||||
|
* @param url The URL to sanitize
|
||||||
|
*/
|
||||||
|
export const sanitizeRedirectionUrl = (url?: string) => {
|
||||||
|
if (url && url.startsWith("/") && !url.startsWith("//")) {
|
||||||
|
return url;
|
||||||
|
} else {
|
||||||
|
return "/"; // Safe default
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -105,6 +105,10 @@ const getSandboxFlags = (
|
|||||||
baseSandbox.push("allow-popups-to-escape-sandbox");
|
baseSandbox.push("allow-popups-to-escape-sandbox");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (permissions.allowModals) {
|
||||||
|
baseSandbox.push("allow-modals");
|
||||||
|
}
|
||||||
|
|
||||||
return baseSandbox;
|
return baseSandbox;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,4 +119,5 @@ const permissionMapping = {
|
|||||||
allowGeolocation: "geolocation",
|
allowGeolocation: "geolocation",
|
||||||
allowMicrophone: "microphone",
|
allowMicrophone: "microphone",
|
||||||
allowPayment: "payment",
|
allowPayment: "payment",
|
||||||
|
allowModals: "allow-modals",
|
||||||
} satisfies Record<keyof Omit<WidgetComponentProps<"iframe">["options"], "embedUrl" | "allowScrolling">, string>;
|
} satisfies Record<keyof Omit<WidgetComponentProps<"iframe">["options"], "embedUrl" | "allowScrolling">, string>;
|
||||||
@@ -17,6 +17,7 @@ export const { definition, componentLoader } = createWidgetDefinition("iframe",
|
|||||||
allowMicrophone: factory.switch(),
|
allowMicrophone: factory.switch(),
|
||||||
allowCamera: factory.switch(),
|
allowCamera: factory.switch(),
|
||||||
allowGeolocation: factory.switch(),
|
allowGeolocation: factory.switch(),
|
||||||
|
allowModals: factory.switch(),
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
}).withDynamicImport(() => import("./component"));
|
}).withDynamicImport(() => import("./component"));
|
||||||
@@ -79,7 +79,6 @@ const Feed = ({ options }: Pick<WidgetComponentProps<"video">, "options">) => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
// All other properties are updated with other useEffect
|
// All other properties are updated with other useEffect
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [videoRef]);
|
}, [videoRef]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Generated
+20
-32
@@ -438,8 +438,8 @@ importers:
|
|||||||
specifier: 2.2.6
|
specifier: 2.2.6
|
||||||
version: 2.2.6
|
version: 2.2.6
|
||||||
undici:
|
undici:
|
||||||
specifier: 7.18.2
|
specifier: 7.24.5
|
||||||
version: 7.18.2
|
version: 7.24.5
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@homarr/eslint-config':
|
'@homarr/eslint-config':
|
||||||
specifier: workspace:^0.2.0
|
specifier: workspace:^0.2.0
|
||||||
@@ -862,8 +862,8 @@ importers:
|
|||||||
specifier: 19.2.4
|
specifier: 19.2.4
|
||||||
version: 19.2.4(react@19.2.4)
|
version: 19.2.4(react@19.2.4)
|
||||||
undici:
|
undici:
|
||||||
specifier: 7.18.2
|
specifier: 7.24.5
|
||||||
version: 7.18.2
|
version: 7.24.5
|
||||||
zod:
|
zod:
|
||||||
specifier: ^4.2.1
|
specifier: ^4.2.1
|
||||||
version: 4.2.1
|
version: 4.2.1
|
||||||
@@ -1455,7 +1455,7 @@ importers:
|
|||||||
version: link:../image-proxy
|
version: link:../image-proxy
|
||||||
'@homarr/node-unifi':
|
'@homarr/node-unifi':
|
||||||
specifier: ^2.6.0
|
specifier: ^2.6.0
|
||||||
version: 2.6.0(undici@7.18.2)
|
version: 2.6.0(undici@7.24.5)
|
||||||
'@homarr/redis':
|
'@homarr/redis':
|
||||||
specifier: workspace:^0.1.0
|
specifier: workspace:^0.1.0
|
||||||
version: link:../redis
|
version: link:../redis
|
||||||
@@ -1493,8 +1493,8 @@ importers:
|
|||||||
specifier: ^2.1.8
|
specifier: ^2.1.8
|
||||||
version: 2.1.8
|
version: 2.1.8
|
||||||
undici:
|
undici:
|
||||||
specifier: 7.18.2
|
specifier: 7.24.5
|
||||||
version: 7.18.2
|
version: 7.24.5
|
||||||
xml2js:
|
xml2js:
|
||||||
specifier: ^0.6.2
|
specifier: ^0.6.2
|
||||||
version: 0.6.2
|
version: 0.6.2
|
||||||
@@ -1864,8 +1864,8 @@ importers:
|
|||||||
specifier: 2.2.6
|
specifier: 2.2.6
|
||||||
version: 2.2.6
|
version: 2.2.6
|
||||||
undici:
|
undici:
|
||||||
specifier: 7.18.2
|
specifier: 7.24.5
|
||||||
version: 7.18.2
|
version: 7.24.5
|
||||||
zod:
|
zod:
|
||||||
specifier: ^4.2.1
|
specifier: ^4.2.1
|
||||||
version: 4.2.1
|
version: 4.2.1
|
||||||
@@ -10424,20 +10424,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==}
|
resolution: {integrity: sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==}
|
||||||
engines: {node: '>=18.17'}
|
engines: {node: '>=18.17'}
|
||||||
|
|
||||||
undici@7.18.2:
|
|
||||||
resolution: {integrity: sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw==}
|
|
||||||
engines: {node: '>=20.18.1'}
|
|
||||||
|
|
||||||
undici@7.21.0:
|
|
||||||
resolution: {integrity: sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg==}
|
|
||||||
engines: {node: '>=20.18.1'}
|
|
||||||
|
|
||||||
undici@7.24.0:
|
undici@7.24.0:
|
||||||
resolution: {integrity: sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==}
|
resolution: {integrity: sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==}
|
||||||
engines: {node: '>=20.18.1'}
|
engines: {node: '>=20.18.1'}
|
||||||
|
|
||||||
undici@7.24.4:
|
undici@7.24.5:
|
||||||
resolution: {integrity: sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w==}
|
resolution: {integrity: sha512-3IWdCpjgxp15CbJnsi/Y9TCDE7HWVN19j1hmzVhoAkY/+CJx449tVxT5wZc1Gwg8J+P0LWvzlBzxYRnHJ+1i7Q==}
|
||||||
engines: {node: '>=20.18.1'}
|
engines: {node: '>=20.18.1'}
|
||||||
|
|
||||||
unicode-emoji-modifier-base@1.0.0:
|
unicode-emoji-modifier-base@1.0.0:
|
||||||
@@ -11904,11 +11896,11 @@ snapshots:
|
|||||||
|
|
||||||
'@homarr/gridstack@1.12.0': {}
|
'@homarr/gridstack@1.12.0': {}
|
||||||
|
|
||||||
'@homarr/node-unifi@2.6.0(undici@7.18.2)':
|
'@homarr/node-unifi@2.6.0(undici@7.24.5)':
|
||||||
dependencies:
|
dependencies:
|
||||||
axios: 1.9.0
|
axios: 1.9.0
|
||||||
eventemitter2: 6.4.9
|
eventemitter2: 6.4.9
|
||||||
http-cookie-agent: 6.0.8(tough-cookie@5.1.2)(undici@7.18.2)
|
http-cookie-agent: 6.0.8(tough-cookie@5.1.2)(undici@7.24.5)
|
||||||
tough-cookie: 5.1.2
|
tough-cookie: 5.1.2
|
||||||
ws: 8.19.0
|
ws: 8.19.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -12884,7 +12876,7 @@ snapshots:
|
|||||||
p-filter: 4.1.0
|
p-filter: 4.1.0
|
||||||
semantic-release: 25.0.3(typescript@5.9.3)
|
semantic-release: 25.0.3(typescript@5.9.3)
|
||||||
tinyglobby: 0.2.15
|
tinyglobby: 0.2.15
|
||||||
undici: 7.18.2
|
undici: 7.24.5
|
||||||
url-join: 5.0.0
|
url-join: 5.0.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -16593,12 +16585,12 @@ snapshots:
|
|||||||
|
|
||||||
html-url-attributes@3.0.1: {}
|
html-url-attributes@3.0.1: {}
|
||||||
|
|
||||||
http-cookie-agent@6.0.8(tough-cookie@5.1.2)(undici@7.18.2):
|
http-cookie-agent@6.0.8(tough-cookie@5.1.2)(undici@7.24.5):
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 7.1.3
|
agent-base: 7.1.3
|
||||||
tough-cookie: 5.1.2
|
tough-cookie: 5.1.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
undici: 7.18.2
|
undici: 7.24.5
|
||||||
|
|
||||||
http-errors@2.0.0:
|
http-errors@2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -17080,7 +17072,7 @@ snapshots:
|
|||||||
saxes: 6.0.0
|
saxes: 6.0.0
|
||||||
symbol-tree: 3.2.4
|
symbol-tree: 3.2.4
|
||||||
tough-cookie: 6.0.0
|
tough-cookie: 6.0.0
|
||||||
undici: 7.21.0
|
undici: 7.24.5
|
||||||
w3c-xmlserializer: 5.0.0
|
w3c-xmlserializer: 5.0.0
|
||||||
webidl-conversions: 8.0.1
|
webidl-conversions: 8.0.1
|
||||||
whatwg-mimetype: 5.0.0
|
whatwg-mimetype: 5.0.0
|
||||||
@@ -17107,7 +17099,7 @@ snapshots:
|
|||||||
saxes: 6.0.0
|
saxes: 6.0.0
|
||||||
symbol-tree: 3.2.4
|
symbol-tree: 3.2.4
|
||||||
tough-cookie: 6.0.1
|
tough-cookie: 6.0.1
|
||||||
undici: 7.24.4
|
undici: 7.24.5
|
||||||
w3c-xmlserializer: 5.0.0
|
w3c-xmlserializer: 5.0.0
|
||||||
webidl-conversions: 8.0.1
|
webidl-conversions: 8.0.1
|
||||||
whatwg-mimetype: 5.0.0
|
whatwg-mimetype: 5.0.0
|
||||||
@@ -19740,7 +19732,7 @@ snapshots:
|
|||||||
ssh-remote-port-forward: 1.0.4
|
ssh-remote-port-forward: 1.0.4
|
||||||
tar-fs: 3.1.2
|
tar-fs: 3.1.2
|
||||||
tmp: 0.2.5
|
tmp: 0.2.5
|
||||||
undici: 7.24.4
|
undici: 7.24.5
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bare-buffer
|
- bare-buffer
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -20080,13 +20072,9 @@ snapshots:
|
|||||||
|
|
||||||
undici@6.23.0: {}
|
undici@6.23.0: {}
|
||||||
|
|
||||||
undici@7.18.2: {}
|
|
||||||
|
|
||||||
undici@7.21.0: {}
|
|
||||||
|
|
||||||
undici@7.24.0: {}
|
undici@7.24.0: {}
|
||||||
|
|
||||||
undici@7.24.4: {}
|
undici@7.24.5: {}
|
||||||
|
|
||||||
unicode-emoji-modifier-base@1.0.0: {}
|
unicode-emoji-modifier-base@1.0.0: {}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user