mirror of
https://github.com/ajnart/homarr.git
synced 2026-02-26 16:30:57 +01:00
feat: add nextcloud integration (#2501)
This commit is contained in:
1
apps/nextjs/public/images/apps/nextcloud.svg
Normal file
1
apps/nextjs/public/images/apps/nextcloud.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 139.3 512.2 233.5"><path d="M256 139.3c-53 0-97.9 35.8-112.1 84.4-12.2-25.5-38.2-43.4-68.2-43.4C34.2 180.2 0 214.4 0 256s34.2 75.8 75.8 75.8c30 0 55.9-17.9 68.2-43.4 14.1 48.6 59.1 84.4 112.1 84.4S354 337 368.2 288.4c12.2 25.5 38.2 43.4 68.2 43.4 41.6 0 75.8-34.2 75.8-75.8s-34.2-75.8-75.8-75.8c-30 0-55.9 17.9-68.2 43.4-14.3-48.5-59.2-84.3-112.2-84.3m0 45c39.9 0 71.7 31.8 71.7 71.7s-31.8 71.7-71.7 71.7-71.7-31.8-71.7-71.7 31.8-71.7 71.7-71.7m-180.2 41c17.2 0 30.7 13.5 30.7 30.7S93 286.7 75.8 286.7 45.1 273.2 45.1 256s13.4-30.7 30.7-30.7m360.4 0c17.2 0 30.7 13.5 30.7 30.7s-13.5 30.7-30.7 30.7-30.7-13.5-30.7-30.7 13.5-30.7 30.7-30.7" style="fill:#3784c9"/></svg>
|
||||
|
After Width: | Height: | Size: 739 B |
@@ -151,6 +151,12 @@ export const integrationDefs = {
|
||||
category: ["healthMonitoring"],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/proxmox.svg",
|
||||
},
|
||||
nextcloud: {
|
||||
name: "Nextcloud",
|
||||
secretKinds: [["username", "password"]],
|
||||
category: ["calendar"],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/nextcloud.svg",
|
||||
},
|
||||
} as const satisfies Record<string, integrationDefinition>;
|
||||
|
||||
export const integrationKinds = objectKeys(integrationDefs) as AtLeastOneOf<IntegrationKind>;
|
||||
|
||||
@@ -36,7 +36,9 @@
|
||||
"@homarr/translation": "workspace:^0.1.0",
|
||||
"@homarr/validation": "workspace:^0.1.0",
|
||||
"@jellyfin/sdk": "^0.11.0",
|
||||
"node-ical": "^0.20.1",
|
||||
"proxmox-api": "1.1.1",
|
||||
"tsdav": "^2.1.3",
|
||||
"undici": "7.4.0",
|
||||
"xml2js": "^0.6.2",
|
||||
"zod": "^3.24.2"
|
||||
|
||||
@@ -19,6 +19,7 @@ import { RadarrIntegration } from "../media-organizer/radarr/radarr-integration"
|
||||
import { ReadarrIntegration } from "../media-organizer/readarr/readarr-integration";
|
||||
import { SonarrIntegration } from "../media-organizer/sonarr/sonarr-integration";
|
||||
import { TdarrIntegration } from "../media-transcoding/tdarr-integration";
|
||||
import { NextcloudIntegration } from "../nextcloud/nextcloud.integration";
|
||||
import { OpenMediaVaultIntegration } from "../openmediavault/openmediavault-integration";
|
||||
import { OverseerrIntegration } from "../overseerr/overseerr-integration";
|
||||
import { createPiHoleIntegrationAsync } from "../pi-hole/pi-hole-integration-factory";
|
||||
@@ -86,6 +87,7 @@ export const integrationCreators = {
|
||||
tdarr: TdarrIntegration,
|
||||
proxmox: ProxmoxIntegration,
|
||||
emby: EmbyIntegration,
|
||||
nextcloud: NextcloudIntegration,
|
||||
} satisfies Record<IntegrationKind, IntegrationInstance | [(input: IntegrationInput) => Promise<Integration>]>;
|
||||
|
||||
type IntegrationInstanceOfKind<TKind extends keyof typeof integrationCreators> = {
|
||||
|
||||
@@ -19,6 +19,7 @@ export { PlexIntegration } from "./plex/plex-integration";
|
||||
export { ProwlarrIntegration } from "./prowlarr/prowlarr-integration";
|
||||
export { LidarrIntegration } from "./media-organizer/lidarr/lidarr-integration";
|
||||
export { ReadarrIntegration } from "./media-organizer/readarr/readarr-integration";
|
||||
export { NextcloudIntegration } from "./nextcloud/nextcloud.integration";
|
||||
|
||||
// Types
|
||||
export type { IntegrationInput } from "./base/integration";
|
||||
|
||||
97
packages/integrations/src/nextcloud/nextcloud.integration.ts
Normal file
97
packages/integrations/src/nextcloud/nextcloud.integration.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import dayjs from "dayjs";
|
||||
import objectSupport from "dayjs/plugin/objectSupport";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
import * as ical from "node-ical";
|
||||
import { DAVClient } from "tsdav";
|
||||
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
import { Integration } from "../base/integration";
|
||||
import type { CalendarEvent } from "../calendar-types";
|
||||
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(objectSupport);
|
||||
|
||||
export class NextcloudIntegration extends Integration {
|
||||
public async testConnectionAsync(): Promise<void> {
|
||||
const client = this.createCalendarClient();
|
||||
await client.login();
|
||||
}
|
||||
|
||||
public async getCalendarEventsAsync(start: Date, end: Date): Promise<CalendarEvent[]> {
|
||||
const client = this.createCalendarClient();
|
||||
await client.login();
|
||||
|
||||
const calendars = await client.fetchCalendars();
|
||||
// Parameters must be in ISO-8601, See https://tsdav.vercel.app/docs/caldav/fetchCalendarObjects#arguments
|
||||
const calendarEvents = (
|
||||
await Promise.all(
|
||||
calendars.map(
|
||||
async (calendar) =>
|
||||
await client.fetchCalendarObjects({
|
||||
calendar,
|
||||
timeRange: { start: start.toISOString(), end: end.toISOString() },
|
||||
}),
|
||||
),
|
||||
)
|
||||
).flat();
|
||||
|
||||
return calendarEvents.map((event): CalendarEvent => {
|
||||
// @ts-expect-error the typescript definitions for this package are wrong
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
|
||||
const icalData = ical.default.parseICS(event.data) as ical.CalendarResponse;
|
||||
const veventObject = Object.values(icalData).find((data) => data.type === "VEVENT");
|
||||
|
||||
if (!veventObject) {
|
||||
throw new Error(`Invalid event data object: ${JSON.stringify(event.data)}. Unable to process the calendar.`);
|
||||
}
|
||||
|
||||
logger.debug(`Converting VEVENT event to ${event.etag} from Nextcloud: ${JSON.stringify(veventObject)}`);
|
||||
|
||||
const date = dayjs.utc({
|
||||
days: veventObject.start.getDay(),
|
||||
month: veventObject.start.getMonth(),
|
||||
year: veventObject.start.getFullYear(),
|
||||
hours: veventObject.start.getHours(),
|
||||
minutes: veventObject.start.getMinutes(),
|
||||
seconds: veventObject.start.getSeconds(),
|
||||
});
|
||||
|
||||
const eventUrlWithoutHost = new URL(event.url).pathname;
|
||||
const dateInMillis = veventObject.start.valueOf();
|
||||
|
||||
const url = this.url(
|
||||
`/apps/calendar/timeGridWeek/now/edit/sidebar/${Buffer.from(eventUrlWithoutHost).toString("base64url")}/${dateInMillis / 1000}`,
|
||||
);
|
||||
|
||||
return {
|
||||
name: veventObject.summary,
|
||||
date: date.toDate(),
|
||||
subName: "",
|
||||
description: veventObject.description,
|
||||
links: [
|
||||
{
|
||||
href: url.toString(),
|
||||
name: "Nextcloud",
|
||||
logo: "/images/apps/nextcloud.svg",
|
||||
color: undefined,
|
||||
notificationColor: "#ff8600",
|
||||
isDark: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private createCalendarClient() {
|
||||
return new DAVClient({
|
||||
serverUrl: this.integration.url,
|
||||
credentials: {
|
||||
username: this.getSecretValue("username"),
|
||||
password: this.getSecretValue("password"),
|
||||
},
|
||||
authMethod: "Basic",
|
||||
defaultAccountType: "caldav",
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,13 @@ export const CalendarEventList = ({ events }: CalendarEventListProps) => {
|
||||
{events.map((event, eventIndex) => (
|
||||
<Group key={`event-${eventIndex}`} align={"stretch"} wrap="nowrap">
|
||||
<Box pos={"relative"} w={70} h={120}>
|
||||
<Image src={event.thumbnail} w={70} h={120} radius={"sm"} />
|
||||
<Image
|
||||
src={event.thumbnail}
|
||||
w={70}
|
||||
h={120}
|
||||
radius={"sm"}
|
||||
fallbackSrc={"https://placehold.co/400x600?text=No%20image"}
|
||||
/>
|
||||
{event.mediaInformation?.type === "tv" && (
|
||||
<Badge
|
||||
pos={"absolute"}
|
||||
|
||||
81
pnpm-lock.yaml
generated
81
pnpm-lock.yaml
generated
@@ -1294,9 +1294,15 @@ importers:
|
||||
'@jellyfin/sdk':
|
||||
specifier: ^0.11.0
|
||||
version: 0.11.0(axios@1.7.7)
|
||||
node-ical:
|
||||
specifier: ^0.20.1
|
||||
version: 0.20.1
|
||||
proxmox-api:
|
||||
specifier: 1.1.1
|
||||
version: 1.1.1
|
||||
tsdav:
|
||||
specifier: ^2.1.3
|
||||
version: 2.1.3
|
||||
undici:
|
||||
specifier: 7.4.0
|
||||
version: 7.4.0
|
||||
@@ -1474,7 +1480,7 @@ importers:
|
||||
version: link:../ui
|
||||
'@mantine/notifications':
|
||||
specifier: ^7.17.1
|
||||
version: 7.17.1(@mantine/core@7.17.1(@mantine/hooks@7.17.1(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@mantine/hooks@7.17.1(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
version: 7.17.1(@mantine/core@7.17.1(@mantine/hooks@7.17.1(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@mantine/hooks@7.17.1(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
'@tabler/icons-react':
|
||||
specifier: ^3.31.0
|
||||
version: 3.31.0(react@19.0.0)
|
||||
@@ -1827,7 +1833,7 @@ importers:
|
||||
version: 7.17.1(react@19.0.0)
|
||||
'@mantine/spotlight':
|
||||
specifier: ^7.17.1
|
||||
version: 7.17.1(@mantine/core@7.17.1(@mantine/hooks@7.17.1(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@mantine/hooks@7.17.1(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
version: 7.17.1(@mantine/core@7.17.1(@mantine/hooks@7.17.1(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@mantine/hooks@7.17.1(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
'@tabler/icons-react':
|
||||
specifier: ^3.31.0
|
||||
version: 3.31.0(react@19.0.0)
|
||||
@@ -5211,6 +5217,9 @@ packages:
|
||||
bare-stream@2.3.0:
|
||||
resolution: {integrity: sha512-pVRWciewGUeCyKEuRxwv06M079r+fRjAQjBEK2P6OYGrO43O+Z0LrPZZEjlc4mB6C2RpZ9AxJ1s7NLEtOHO6eA==}
|
||||
|
||||
base-64@1.0.0:
|
||||
resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==}
|
||||
|
||||
base64-arraybuffer@1.0.2:
|
||||
resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
|
||||
engines: {node: '>= 0.6.0'}
|
||||
@@ -5649,6 +5658,9 @@ packages:
|
||||
engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'}
|
||||
hasBin: true
|
||||
|
||||
cross-fetch@4.0.0:
|
||||
resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
|
||||
|
||||
cross-fetch@4.1.0:
|
||||
resolution: {integrity: sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==}
|
||||
|
||||
@@ -7631,6 +7643,12 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
moment-timezone@0.5.47:
|
||||
resolution: {integrity: sha512-UbNt/JAWS0m/NJOebR0QMRHBk0hu03r5dx9GK8Cs0AS3I81yDcOc9k+DytPItgVvBP7J6Mf6U2n3BPAacAV9oA==}
|
||||
|
||||
moment@2.30.1:
|
||||
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
|
||||
|
||||
mpd-parser@1.3.1:
|
||||
resolution: {integrity: sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw==}
|
||||
hasBin: true
|
||||
@@ -7815,6 +7833,9 @@ packages:
|
||||
resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==}
|
||||
hasBin: true
|
||||
|
||||
node-ical@0.20.1:
|
||||
resolution: {integrity: sha512-NrXgzDJd6XcyX9kDMJVA3xYCZmntY7ghA2BOdBeYr3iu8tydHOAb+68jPQhF9V2CRQ0/386X05XhmLzQUN0+Hw==}
|
||||
|
||||
node-loader@2.1.0:
|
||||
resolution: {integrity: sha512-OwjPkyh8+7jW8DMd/iq71uU1Sspufr/C2+c3t0p08J3CrM9ApZ4U53xuisNrDXOHyGi5OYHgtfmmh+aK9zJA6g==}
|
||||
engines: {node: '>= 10.13.0'}
|
||||
@@ -8795,6 +8816,9 @@ packages:
|
||||
rrdom@0.1.7:
|
||||
resolution: {integrity: sha512-ZLd8f14z9pUy2Hk9y636cNv5Y2BMnNEY99wxzW9tD2BLDfe1xFxtLjB4q/xCBYo6HRe0wofzKzjm4JojmpBfFw==}
|
||||
|
||||
rrule@2.8.1:
|
||||
resolution: {integrity: sha512-hM3dHSBMeaJ0Ktp7W38BJZ7O1zOgaFEsn41PDk+yHoEtfLV+PoJt9E9xAlZiWgf/iqEqionN0ebHFZIDAp+iGw==}
|
||||
|
||||
rrweb-cssom@0.8.0:
|
||||
resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==}
|
||||
|
||||
@@ -9517,6 +9541,10 @@ packages:
|
||||
tsconfig-paths@3.15.0:
|
||||
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
|
||||
|
||||
tsdav@2.1.3:
|
||||
resolution: {integrity: sha512-TwPBYZKLlbJNtmfg5QzeGqRnOYZ4CCuII3D528+Vv8K/les0PmyB7sT7gf967a6SduJKxCVovWZ+Ei3O+cCAlg==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
tslib@1.14.1:
|
||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||
|
||||
@@ -10129,6 +10157,10 @@ packages:
|
||||
xml-but-prettier@1.0.1:
|
||||
resolution: {integrity: sha512-C2CJaadHrZTqESlH03WOyw0oZTtoy2uEg6dSDF6YRg+9GnYNub53RRemLpnvtbHDFelxMx4LajiFsYeR6XJHgQ==}
|
||||
|
||||
xml-js@1.6.11:
|
||||
resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==}
|
||||
hasBin: true
|
||||
|
||||
xml-name-validator@5.0.0:
|
||||
resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -11220,7 +11252,7 @@ snapshots:
|
||||
react: 19.0.0
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
|
||||
'@mantine/notifications@7.17.1(@mantine/core@7.17.1(@mantine/hooks@7.17.1(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@mantine/hooks@7.17.1(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||
'@mantine/notifications@7.17.1(@mantine/core@7.17.1(@mantine/hooks@7.17.1(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@mantine/hooks@7.17.1(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||
dependencies:
|
||||
'@mantine/core': 7.17.1(@mantine/hooks@7.17.1(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
'@mantine/hooks': 7.17.1(react@19.0.0)
|
||||
@@ -11229,7 +11261,7 @@ snapshots:
|
||||
react-dom: 19.0.0(react@19.0.0)
|
||||
react-transition-group: 4.4.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
|
||||
'@mantine/spotlight@7.17.1(@mantine/core@7.17.1(@mantine/hooks@7.17.1(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@mantine/hooks@7.17.1(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||
'@mantine/spotlight@7.17.1(@mantine/core@7.17.1(@mantine/hooks@7.17.1(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(@mantine/hooks@7.17.1(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||
dependencies:
|
||||
'@mantine/core': 7.17.1(@mantine/hooks@7.17.1(react@19.0.0))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
'@mantine/hooks': 7.17.1(react@19.0.0)
|
||||
@@ -13468,6 +13500,8 @@ snapshots:
|
||||
streamx: 2.20.1
|
||||
optional: true
|
||||
|
||||
base-64@1.0.0: {}
|
||||
|
||||
base64-arraybuffer@1.0.2: {}
|
||||
|
||||
base64-js@1.5.1: {}
|
||||
@@ -13929,6 +13963,12 @@ snapshots:
|
||||
dependencies:
|
||||
cross-spawn: 7.0.3
|
||||
|
||||
cross-fetch@4.0.0:
|
||||
dependencies:
|
||||
node-fetch: 2.7.0
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
cross-fetch@4.1.0:
|
||||
dependencies:
|
||||
node-fetch: 2.7.0
|
||||
@@ -16173,6 +16213,12 @@ snapshots:
|
||||
|
||||
mkdirp@1.0.4: {}
|
||||
|
||||
moment-timezone@0.5.47:
|
||||
dependencies:
|
||||
moment: 2.30.1
|
||||
|
||||
moment@2.30.1: {}
|
||||
|
||||
mpd-parser@1.3.1:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.6
|
||||
@@ -16338,6 +16384,15 @@ snapshots:
|
||||
node-gyp-build@4.8.4:
|
||||
optional: true
|
||||
|
||||
node-ical@0.20.1:
|
||||
dependencies:
|
||||
axios: 1.7.7
|
||||
moment-timezone: 0.5.47
|
||||
rrule: 2.8.1
|
||||
uuid: 10.0.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
|
||||
node-loader@2.1.0(webpack@5.94.0):
|
||||
dependencies:
|
||||
loader-utils: 2.0.4
|
||||
@@ -17386,6 +17441,10 @@ snapshots:
|
||||
dependencies:
|
||||
rrweb-snapshot: 2.0.0-alpha.4
|
||||
|
||||
rrule@2.8.1:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
rrweb-cssom@0.8.0: {}
|
||||
|
||||
rrweb-player@1.0.0-alpha.4:
|
||||
@@ -18313,6 +18372,16 @@ snapshots:
|
||||
minimist: 1.2.8
|
||||
strip-bom: 3.0.0
|
||||
|
||||
tsdav@2.1.3:
|
||||
dependencies:
|
||||
base-64: 1.0.0
|
||||
cross-fetch: 4.0.0
|
||||
debug: 4.4.0
|
||||
xml-js: 1.6.11
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
|
||||
tslib@1.14.1: {}
|
||||
|
||||
tslib@2.7.0: {}
|
||||
@@ -18981,6 +19050,10 @@ snapshots:
|
||||
dependencies:
|
||||
repeat-string: 1.6.1
|
||||
|
||||
xml-js@1.6.11:
|
||||
dependencies:
|
||||
sax: 1.4.1
|
||||
|
||||
xml-name-validator@5.0.0: {}
|
||||
|
||||
xml2js@0.6.2:
|
||||
|
||||
Reference in New Issue
Block a user