diff --git a/__mocks__/@nextcloud/auth.js b/__mocks__/@nextcloud/auth.js index 821eaf3e..b6bfcda5 100644 --- a/__mocks__/@nextcloud/auth.js +++ b/__mocks__/@nextcloud/auth.js @@ -5,3 +5,7 @@ export const getCurrentUser = function() { isAdmin: false, } } + +export const getRequestToken = function() { + return 'some-token-string' +} diff --git a/__mocks__/@nextcloud/router.js b/__mocks__/@nextcloud/router.js new file mode 100644 index 00000000..b05f9694 --- /dev/null +++ b/__mocks__/@nextcloud/router.js @@ -0,0 +1 @@ +export const generateRemoteUrl = (path) => `https://localhost/${path}` diff --git a/__tests__/dav/dav.spec.ts b/__tests__/dav/dav.spec.ts new file mode 100644 index 00000000..12738dee --- /dev/null +++ b/__tests__/dav/dav.spec.ts @@ -0,0 +1,77 @@ +import { afterAll, describe, expect, test, vi } from 'vitest' +import { readFile } from 'fs/promises' + +import { File, Folder, davDefaultRootUrl, davGetDefaultPropfind, davGetFavoritesReport, davRootPath, getFavoriteNodes } from '../../lib' + +vi.mock('@nextcloud/auth') +vi.mock('@nextcloud/router') + +afterAll(() => { + vi.resetAllMocks() +}) + +describe('DAV functions', () => { + test('root path is correct', () => { + expect(davRootPath).toBe('/files/test') + }) + + test('root url is correct', () => { + expect(davDefaultRootUrl).toBe('https://localhost/dav/files/test') + }) +}) + +describe('DAV requests', () => { + test('request all favorite files', async () => { + const favoritesResponseJSON = JSON.parse((await readFile(new URL('../fixtures/favorites-response.json', import.meta.url))).toString()) + + // Mock the WebDAV client + const client = { + getDirectoryContents: vi.fn((path: string, options: any) => { + if (options?.details) { + return { + data: favoritesResponseJSON, + } + } + return favoritesResponseJSON + }), + } + + const nodes = await getFavoriteNodes(client as never) + // Check client was called correctly + expect(client.getDirectoryContents).toBeCalled() + expect(client.getDirectoryContents.mock.lastCall?.at(0)).toBe('/') + expect(client.getDirectoryContents.mock.lastCall?.at(1)?.data).toBe(davGetFavoritesReport()) + expect(client.getDirectoryContents.mock.lastCall?.at(1)?.headers?.method).toBe('REPORT') + // Check for correct output + expect(nodes.length).toBe(2) + expect(nodes[0] instanceof Folder).toBe(true) + expect(nodes[0].basename).toBe('Neuer Ordner') + expect(nodes[0].mtime?.getTime()).toBe(Date.parse('Mon, 24 Jul 2023 16:30:44 GMT')) + expect(nodes[1] instanceof File).toBe(true) + }) + + test('request inner favorites', async () => { + const favoritesResponseJSON = JSON.parse((await readFile(new URL('../fixtures/favorites-inner-response.json', import.meta.url))).toString()) + + // Mock the WebDAV client + const client = { + getDirectoryContents: vi.fn((path: string, options: any) => { + if (options?.details) { + return { + data: favoritesResponseJSON, + } + } + return favoritesResponseJSON + }), + } + + const nodes = await getFavoriteNodes(client as never, '/Neuer Ordner') + // Check client was called correctly + expect(client.getDirectoryContents).toBeCalled() + expect(client.getDirectoryContents.mock.lastCall?.at(0)).toBe('/Neuer Ordner') + expect(client.getDirectoryContents.mock.lastCall?.at(1)?.data).toBe(davGetDefaultPropfind()) + expect(client.getDirectoryContents.mock.lastCall?.at(1)?.headers?.method).toBe('PROPFIND') + // There are no inner nodes + expect(nodes.length).toBe(0) + }) +}) diff --git a/__tests__/permissions.spec.ts b/__tests__/dav/davPermissions.spec.ts similarity index 84% rename from __tests__/permissions.spec.ts rename to __tests__/dav/davPermissions.spec.ts index d83d1db1..c85ba85b 100644 --- a/__tests__/permissions.spec.ts +++ b/__tests__/dav/davPermissions.spec.ts @@ -1,6 +1,7 @@ import { describe, it, expect } from 'vitest' -import { parseWebdavPermissions, Permission } from '../lib/permissions' +import { davParsePermissions } from '../../lib/dav/davPermissions' +import { Permission } from '../../lib/permissions' const dataSet = [ { input: undefined, permissions: Permission.NONE }, @@ -21,11 +22,11 @@ const dataSet = [ { input: 'RGDNVCK', permissions: Permission.UPDATE | Permission.READ | Permission.DELETE | Permission.CREATE | Permission.SHARE }, ] -describe('parseWebdavPermissions', () => { +describe('davParsePermissions', () => { dataSet.forEach(({ input, permissions }) => { it(`expect ${input} to be ${permissions}`, () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any - expect(parseWebdavPermissions(input as any as string)).toBe(permissions) + expect(davParsePermissions(input as any as string)).toBe(permissions) }) }) }) diff --git a/__tests__/dav/davProperties.spec.ts b/__tests__/dav/davProperties.spec.ts new file mode 100644 index 00000000..312c306c --- /dev/null +++ b/__tests__/dav/davProperties.spec.ts @@ -0,0 +1,98 @@ +import { beforeEach, describe, expect, test, vi } from 'vitest' +import { XMLValidator } from 'fast-xml-parser' + +import { + davGetDefaultPropfind, + davGetFavoritesReport, + getDavNameSpaces, + getDavProperties, + registerDavProperty, + defaultDavNamespaces, + defaultDavProperties, +} from '../../lib/dav/davProperties' + +import logger from '../../lib/utils/logger' + +describe('DAV Properties', () => { + + beforeEach(() => { + delete window._nc_dav_properties + delete window._nc_dav_namespaces + }) + + test('getDavNameSpaces fall back to defaults', () => { + expect(window._nc_dav_namespaces).toBeUndefined() + const namespace = getDavNameSpaces() + expect(namespace).toBeTruthy() + Object.keys(defaultDavNamespaces).forEach(n => expect(namespace.includes(n) && namespace.includes(defaultDavNamespaces[n])).toBe(true)) + }) + + test('getDavProperties fall back to defaults', () => { + expect(window._nc_dav_properties).toBeUndefined() + const props = getDavProperties() + expect(props).toBeTruthy() + defaultDavProperties.forEach(p => expect(props.includes(p)).toBe(true)) + }) + + test('davGetDefaultPropfind', () => { + expect(typeof davGetDefaultPropfind()).toBe('string') + expect(XMLValidator.validate(davGetDefaultPropfind())).toBe(true) + }) + + test('davGetFavoritesReport', () => { + expect(typeof davGetFavoritesReport()).toBe('string') + expect(XMLValidator.validate(davGetFavoritesReport())).toBe(true) + }) + + test('registerDavProperty registers successfully', () => { + logger.error = vi.fn() + + expect(window._nc_dav_namespaces).toBeUndefined() + expect(window._nc_dav_properties).toBeUndefined() + + expect(registerDavProperty('my:prop', { my: 'https://example.com/ns' })).toBe(true) + expect(logger.error).not.toBeCalled() + expect(getDavProperties().includes('my:prop')).toBe(true) + expect(getDavNameSpaces().includes('xmlns:my="https://example.com/ns"')).toBe(true) + }) + + test('registerDavProperty fails when registered multipletimes', () => { + logger.error = vi.fn() + + expect(window._nc_dav_namespaces).toBeUndefined() + expect(window._nc_dav_properties).toBeUndefined() + + expect(registerDavProperty('my:prop', { my: 'https://example.com/ns' })).toBe(true) + expect(registerDavProperty('my:prop')).toBe(false) + expect(logger.error).toBeCalled() + // but still included + expect(getDavProperties().includes('my:prop')).toBe(true) + expect(getDavNameSpaces().includes('xmlns:my="https://example.com/ns"')).toBe(true) + }) + + test('registerDavProperty fails with invalid props', () => { + logger.error = vi.fn() + + expect(window._nc_dav_namespaces).toBeUndefined() + expect(window._nc_dav_properties).toBeUndefined() + + expect(registerDavProperty('my:prop:invalid', { my: 'https://example.com/ns' })).toBe(false) + expect(logger.error).toBeCalled() + expect(getDavProperties().includes('my:prop')).toBe(false) + + expect(registerDavProperty('', { my: 'https://example.com/ns' })).toBe(false) + expect(logger.error).toBeCalled() + expect(getDavProperties().includes('my:prop')).toBe(false) + }) + + test('registerDavProperty fails with missing namespace', () => { + logger.error = vi.fn() + + expect(window._nc_dav_namespaces).toBeUndefined() + expect(window._nc_dav_properties).toBeUndefined() + + expect(registerDavProperty('my:prop', { other: 'https://example.com/ns' })).toBe(false) + expect(logger.error).toBeCalled() + expect(getDavProperties().includes('my:prop')).toBe(false) + }) +}) diff --git a/__tests__/files/node.spec.ts b/__tests__/files/node.spec.ts index 432734f9..517ffc80 100644 --- a/__tests__/files/node.spec.ts +++ b/__tests__/files/node.spec.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from 'vitest' import { File } from '../../lib/files/file' import { Folder } from '../../lib/files/folder' -import NodeData, { Attribute } from '../../lib/files/nodeData' +import { Attribute, NodeData } from '../../lib/files/nodeData' import { Permission } from '../../lib/permissions' describe('Node testing', () => { diff --git a/__tests__/fixtures/favorites-inner-response.json b/__tests__/fixtures/favorites-inner-response.json new file mode 100644 index 00000000..bb8eb553 --- /dev/null +++ b/__tests__/fixtures/favorites-inner-response.json @@ -0,0 +1 @@ +[{"filename":"/Neuer Ordner","basename":"Neuer Ordner","lastmod":"Mon, 24 Jul 2023 16:30:44 GMT","size":0,"type":"directory","etag":"64bea734d3987","props":{"getetag":"\"64bea734d3987\"","getlastmodified":"Mon, 24 Jul 2023 16:30:44 GMT","quota-available-bytes":-3,"resourcetype":{"collection":""},"has-preview":false,"is-encrypted":0,"mount-type":"","share-attributes":"[]","comments-unread":0,"favorite":1,"fileid":74,"owner-display-name":"user1","owner-id":"user1","permissions":"RGDNVCK","share-types":{"share-type":3},"size":0,"share-permissions":31}}] \ No newline at end of file diff --git a/__tests__/fixtures/favorites-inner-response.xml b/__tests__/fixtures/favorites-inner-response.xml new file mode 100644 index 00000000..9d7b9bf3 --- /dev/null +++ b/__tests__/fixtures/favorites-inner-response.xml @@ -0,0 +1,2 @@ + +/remote.php/dav/files/user1/Neuer%20Ordner/"64bea734d3987"Mon, 24 Jul 2023 16:30:44 GMT-3false0[]0174user1user1RGDNVCK3031HTTP/1.1 200 OKHTTP/1.1 404 Not Found diff --git a/__tests__/fixtures/favorites-response.json b/__tests__/fixtures/favorites-response.json new file mode 100644 index 00000000..a88ddacb --- /dev/null +++ b/__tests__/fixtures/favorites-response.json @@ -0,0 +1 @@ +[{"filename":"/Neuer Ordner","basename":"Neuer Ordner","lastmod":"Mon, 24 Jul 2023 16:30:44 GMT","size":0,"type":"directory","etag":"64bea734d3987","props":{"getetag":"\"64bea734d3987\"","getlastmodified":"Mon, 24 Jul 2023 16:30:44 GMT","quota-available-bytes":-3,"resourcetype":{"collection":""},"has-preview":false,"is-encrypted":0,"mount-type":"","share-attributes":"[]","comments-unread":0,"favorite":1,"fileid":74,"owner-display-name":"user1","owner-id":"user1","permissions":"RGDNVCK","share-types":{"share-type":3},"size":0,"share-permissions":31}},{"filename":"/New folder/Neue Textdatei.md","basename":"Neue Textdatei.md","lastmod":"Tue, 25 Jul 2023 12:29:34 GMT","size":0,"type":"file","etag":"7a27142de0a62ed27a7293dbc16e93bc","mime":"text/markdown","props":{"getcontentlength":0,"getcontenttype":"text/markdown","getetag":"\"7a27142de0a62ed27a7293dbc16e93bc\"","getlastmodified":"Tue, 25 Jul 2023 12:29:34 GMT","resourcetype":"","has-preview":false,"mount-type":"shared","share-attributes":"[{\"scope\":\"permissions\",\"key\":\"download\",\"enabled\":false}]","comments-unread":0,"favorite":1,"fileid":80,"owner-display-name":"admin","owner-id":"admin","permissions":"SRGDNVW","share-types":"","size":0,"share-permissions":19}}] \ No newline at end of file diff --git a/__tests__/fixtures/favorites-response.xml b/__tests__/fixtures/favorites-response.xml new file mode 100644 index 00000000..615194be --- /dev/null +++ b/__tests__/fixtures/favorites-response.xml @@ -0,0 +1,2 @@ + +/remote.php/dav/files/user1/"632a3876842ffbf86f9e02df59829a56"Tue, 25 Jul 2023 12:29:34 GMT-3false0[]0057user1user1RGDNVCK17131HTTP/1.1 200 OKHTTP/1.1 404 Not Found diff --git a/__tests__/index.spec.ts b/__tests__/index.spec.ts index d870cb1d..aa2de643 100644 --- a/__tests__/index.spec.ts +++ b/__tests__/index.spec.ts @@ -10,7 +10,7 @@ import { Folder, Node, Permission, - parseWebdavPermissions, + davParsePermissions, } from '../lib/index' import { Entry, NewFileMenu } from '../lib/newFileMenu' @@ -47,9 +47,9 @@ describe('Exports checks', () => { expect(typeof Permission).toBe('object') }) - test('parseWebdavPermissions', () => { - expect(parseWebdavPermissions).toBeTruthy() - expect(typeof parseWebdavPermissions).toBe('function') + test('davParsePermissions', () => { + expect(davParsePermissions).toBeTruthy() + expect(typeof davParsePermissions).toBe('function') }) test('File', () => { diff --git a/lib/dav/dav.ts b/lib/dav/dav.ts new file mode 100644 index 00000000..1a8b0799 --- /dev/null +++ b/lib/dav/dav.ts @@ -0,0 +1,131 @@ +/** + * @copyright Copyright (c) 2023 John Molakvoæ + * + * @author John Molakvoæ + * @author Ferdinand Thiessen + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +import type { DAVResultResponseProps, FileStat, Response, ResponseDataDetailed, WebDAVClient } from 'webdav' +import type { Node } from '../files/node' + +import { File } from '../files/file' +import { Folder } from '../files/folder' +import { NodeData } from '../files/nodeData' +import { davParsePermissions } from './davPermissions' +import { davGetDefaultPropfind, davGetFavoritesReport } from './davProperties' + +import { getCurrentUser, getRequestToken } from '@nextcloud/auth' +import { generateRemoteUrl } from '@nextcloud/router' +import { createClient, getPatcher, RequestOptions } from 'webdav' +import { request } from 'webdav/dist/node/request.js' + +/** + * Nextcloud DAV result response + */ +interface ResponseProps extends DAVResultResponseProps { + permissions: string + fileid: number + size: number +} + +export const davRootPath = `/files/${getCurrentUser()?.uid}` +export const davDefaultRootUrl = generateRemoteUrl('dav' + davRootPath) + +/** + * Get a WebDAV client configured to include the Nextcloud request token + * + * @param davURL The DAV root URL + */ +export const davGetClient = function(davURL = davDefaultRootUrl) { + const client = createClient(davURL, { + headers: { + requesttoken: getRequestToken() || '', + }, + }) + + /** + * Allow to override the METHOD to support dav REPORT + * + * @see https://github.com/perry-mitchell/webdav-client/blob/8d9694613c978ce7404e26a401c39a41f125f87f/source/request.ts + */ + const patcher = getPatcher() + // https://github.com/perry-mitchell/hot-patcher/issues/6 + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + patcher.patch('request', (options: RequestOptions): Promise => { + if (options.headers?.method) { + options.method = options.headers.method + delete options.headers.method + } + return request(options) + }) + return client +} + +/** + * Use WebDAV to query for favorite Nodes + * + * @param davClient The WebDAV client to use for performing the request + * @param path Base path for the favorites, if unset all favorites are queried + */ +export const getFavoriteNodes = async (davClient: WebDAVClient, path = '/') => { + const contentsResponse = await davClient.getDirectoryContents(path, { + details: true, + // Only filter favorites if we're at the root + data: path === '/' ? davGetFavoritesReport() : davGetDefaultPropfind(), + headers: { + // Patched in WebdavClient.ts + method: path === '/' ? 'REPORT' : 'PROPFIND', + }, + includeSelf: true, + }) as ResponseDataDetailed + + return contentsResponse.data.filter(node => node.filename !== path).map((result) => davResultToNode(result)) +} + +/** + * Covert DAV result `FileStat` to `Node` + * + * @param node The DAV result + * @param davRoot The DAV root path + */ +export const davResultToNode = function(node: FileStat, davRoot = davRootPath): Node { + const props = node.props as ResponseProps + const permissions = davParsePermissions(props?.permissions) + const owner = getCurrentUser()?.uid as string + + const nodeData: NodeData = { + id: (props?.fileid as number) || 0, + source: generateRemoteUrl(`dav${davRoot}${node.filename}`), + mtime: new Date(Date.parse(node.lastmod)), + mime: node.mime as string, + size: (props?.size as number) || 0, + permissions, + owner, + root: davRoot, + attributes: { + ...node, + ...props, + hasPreview: props?.['has-preview'], + }, + } + + delete nodeData.attributes?.props + + return node.type === 'file' ? new File(nodeData) : new Folder(nodeData) +} diff --git a/lib/dav/davPermissions.ts b/lib/dav/davPermissions.ts new file mode 100644 index 00000000..13f5bb86 --- /dev/null +++ b/lib/dav/davPermissions.ts @@ -0,0 +1,46 @@ +/** + * @copyright Copyright (c) 2023 John Molakvoæ + * + * @author John Molakvoæ + * @author Ferdinand Thiessen + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +import { Permission } from '../permissions' + +/** + * Parse the webdav permission string to a permission enum + * + * @param permString The DAV permission string + */ +export const davParsePermissions = function(permString = ''): number { + let permissions = Permission.NONE + + if (!permString) { return permissions } + + if (permString.includes('C') || permString.includes('K')) { permissions |= Permission.CREATE } + + if (permString.includes('G')) { permissions |= Permission.READ } + + if (permString.includes('W') || permString.includes('N') || permString.includes('V')) { permissions |= Permission.UPDATE } + + if (permString.includes('D')) { permissions |= Permission.DELETE } + + if (permString.includes('R')) { permissions |= Permission.SHARE } + + return permissions +} diff --git a/lib/dav/davProperties.ts b/lib/dav/davProperties.ts new file mode 100644 index 00000000..5686aec8 --- /dev/null +++ b/lib/dav/davProperties.ts @@ -0,0 +1,141 @@ +/** + * @copyright Copyright (c) 2023 John Molakvoæ + * + * @author John Molakvoæ + * @author Ferdinand Thiessen + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +import logger from '../utils/logger' + +export type DavProperty = { [key: string]: string } + +export const defaultDavProperties = [ + 'd:getcontentlength', + 'd:getcontenttype', + 'd:getetag', + 'd:getlastmodified', + 'd:quota-available-bytes', + 'd:resourcetype', + 'nc:has-preview', + 'nc:is-encrypted', + 'nc:mount-type', + 'nc:share-attributes', + 'oc:comments-unread', + 'oc:favorite', + 'oc:fileid', + 'oc:owner-display-name', + 'oc:owner-id', + 'oc:permissions', + 'oc:share-types', + 'oc:size', + 'ocs:share-permissions', +] + +export const defaultDavNamespaces = { + d: 'DAV:', + nc: 'http://nextcloud.org/ns', + oc: 'http://owncloud.org/ns', + ocs: 'http://open-collaboration-services.org/ns', +} + +/** + * Register custom DAV properties + * + * Can be used if your app introduces custom DAV properties, so e.g. the files app can make use of it. + * + * @param prop The property + * @param namespace The namespace of the property + */ +export const registerDavProperty = function(prop: string, namespace: DavProperty = { nc: 'http://nextcloud.org/ns' }): boolean { + if (typeof window._nc_dav_properties === 'undefined') { + window._nc_dav_properties = [...defaultDavProperties] + window._nc_dav_namespaces = { ...defaultDavNamespaces } + } + + const namespaces = { ...window._nc_dav_namespaces, ...namespace } + + // Check duplicates + if (window._nc_dav_properties.find(search => search === prop)) { + logger.error(`${prop} already registered`, { prop }) + return false + } + + if (prop.startsWith('<') || prop.split(':').length !== 2) { + logger.error(`${prop} is not valid. See example: 'oc:fileid'`, { prop }) + return false + } + + const ns = prop.split(':')[0] + if (!namespaces[ns]) { + logger.error(`${prop} namespace unknown`, { prop, namespaces }) + return false + } + + window._nc_dav_properties.push(prop) + window._nc_dav_namespaces = namespaces + return true +} + +/** + * Get the registered dav properties + */ +export const getDavProperties = function(): string { + if (typeof window._nc_dav_properties === 'undefined') { + window._nc_dav_properties = [...defaultDavProperties] + } + + return window._nc_dav_properties.map(prop => `<${prop} />`).join(' ') +} + +/** + * Get the registered dav namespaces + */ +export const getDavNameSpaces = function(): string { + if (typeof window._nc_dav_namespaces === 'undefined') { + window._nc_dav_namespaces = { ...defaultDavNamespaces } + } + + return Object.keys(window._nc_dav_namespaces).map(ns => `xmlns:${ns}="${window._nc_dav_namespaces?.[ns]}"`).join(' ') +} + +/** + * Get the default PROPFIND request body + */ +export const davGetDefaultPropfind = function(): string { + return ` + + + ${getDavProperties()} + + ` +} + +/** + * Get the REPORT body to filter for favorite nodes + */ +export const davGetFavoritesReport = function(): string { + return ` + + + ${getDavProperties()} + + + 1 + + ` +} diff --git a/lib/files/folder.ts b/lib/files/folder.ts index d6f6812e..7bbf24bc 100644 --- a/lib/files/folder.ts +++ b/lib/files/folder.ts @@ -21,7 +21,7 @@ */ import { FileType } from './fileType' import { Node } from './node' -import NodeData from './nodeData' +import { NodeData } from './nodeData' export class Folder extends Node { diff --git a/lib/files/node.ts b/lib/files/node.ts index f9273287..dbc25321 100644 --- a/lib/files/node.ts +++ b/lib/files/node.ts @@ -22,7 +22,7 @@ import { basename, extname, dirname } from 'path' import { Permission } from '../permissions' import { FileType } from './fileType' -import NodeData, { Attribute, isDavRessource, validateData } from './nodeData' +import { Attribute, NodeData, isDavRessource, validateData } from './nodeData' export abstract class Node { @@ -228,9 +228,10 @@ export abstract class Node { /** * Rename the node * This aliases the move method for easier usage - * @param basename + * + * @param basename The new name of the node */ - rename(basename) { + rename(basename: string) { if (basename.includes('/')) { throw new Error('Invalid basename') } diff --git a/lib/files/nodeData.ts b/lib/files/nodeData.ts index b3e4124d..a2b808f0 100644 --- a/lib/files/nodeData.ts +++ b/lib/files/nodeData.ts @@ -25,7 +25,7 @@ import { Permission } from '../permissions' export interface Attribute { [key: string]: any } -export default interface NodeData { +export interface NodeData { /** Unique ID */ id?: number @@ -64,12 +64,21 @@ export default interface NodeData { root?: string } +/** + * Check if a node source is from a specific DAV service + * + * @param source The source to check + * @param davService Pattern to check if source is DAV ressource + */ export const isDavRessource = function(source: string, davService: RegExp): boolean { return source.match(davService) !== null } /** * Validate Node construct data + * + * @param data The node data + * @param davService Pattern to check if source is DAV ressource */ export const validateData = (data: NodeData, davService: RegExp) => { if (data.id && (typeof data.id !== 'number' || data.id < 0)) { diff --git a/lib/humanfilesize.ts b/lib/humanfilesize.ts index 3097eddb..37b793c9 100644 --- a/lib/humanfilesize.ts +++ b/lib/humanfilesize.ts @@ -31,7 +31,7 @@ const humanListBinary = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'] * * @param size in bytes * @param skipSmallSizes avoid rendering tiny sizes and return '< 1 KB' instead - * @param binaryPrefixes + * @param binaryPrefixes True if binary prefixes like `KiB` should be used (size base 2) */ export function formatFileSize(size: number|string, skipSmallSizes = false, binaryPrefixes = false): string { diff --git a/lib/index.ts b/lib/index.ts index 31b7c3c9..58cc5957 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -22,18 +22,27 @@ */ import { type Entry, getNewFileMenu } from './newFileMenu' + export { formatFileSize } from './humanfilesize' +export { FileAction, registerFileAction, getFileActions } from './fileAction' export { type Entry } from './newFileMenu' +export { Permission } from './permissions' + +export * from './dav/davProperties' +export * from './dav/davPermissions' +export * from './dav/dav' export { FileType } from './files/fileType' export { File } from './files/file' export { Folder } from './files/folder' export { Node } from './files/node' -export { Permission, parseWebdavPermissions } from './permissions' -export { FileAction, registerFileAction, getFileActions } from './fileAction' + +// TODO: Add FileInfo type! /** * Add a new menu entry to the upload manager menu + * + * @param entry The new file menu entry */ export const addNewFileMenuEntry = function(entry: Entry) { const newFileMenu = getNewFileMenu() @@ -42,6 +51,8 @@ export const addNewFileMenuEntry = function(entry: Entry) { /** * Remove a previously registered entry from the upload menu + * + * @param entry Entry to remove (or name of entry) */ export const removeNewFileMenuEntry = function(entry: Entry | string) { const newFileMenu = getNewFileMenu() diff --git a/lib/permissions.ts b/lib/permissions.ts index 20dd863a..f2ba8edc 100644 --- a/lib/permissions.ts +++ b/lib/permissions.ts @@ -20,6 +20,9 @@ * */ +/** + * Node permissions + */ export enum Permission { NONE = 0, CREATE = 4, @@ -29,25 +32,3 @@ export enum Permission { SHARE = 16, ALL = 31, } - -/** - * Parse the webdav permission string to a permission enum - * @see https://github.com/nextcloud/server/blob/71f698649f578db19a22457cb9d420fb62c10382/lib/public/Files/DavUtil.php#L58-L88 - */ -export const parseWebdavPermissions = function(permString = ''): number { - let permissions = Permission.NONE - - if (!permString) { return permissions } - - if (permString.includes('C') || permString.includes('K')) { permissions |= Permission.CREATE } - - if (permString.includes('G')) { permissions |= Permission.READ } - - if (permString.includes('W') || permString.includes('N') || permString.includes('V')) { permissions |= Permission.UPDATE } - - if (permString.includes('D')) { permissions |= Permission.DELETE } - - if (permString.includes('R')) { permissions |= Permission.SHARE } - - return permissions -} diff --git a/package-lock.json b/package-lock.json index 5c65bb42..e77ac35c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,9 @@ "dependencies": { "@nextcloud/auth": "^2.1.0", "@nextcloud/l10n": "^2.2.0", - "@nextcloud/logger": "^2.5.0" + "@nextcloud/logger": "^2.5.0", + "@nextcloud/router": "^2.1.2", + "webdav": "^5.2.3" }, "devDependencies": { "@nextcloud/eslint-config": "^8.3.0-beta.2", @@ -23,7 +25,7 @@ "@susnux/nextcloud-vite-config": "^1.0.0-beta.16", "@types/node": "^20.4.5", "@vitest/coverage-istanbul": "^0.33.0", - "jest-environment-jsdom": "^29.6.1", + "fast-xml-parser": "^4.2.6", "rollup": "^3.26.3", "tslib": "^2.6.1", "typedoc": "^0.24.8", @@ -367,6 +369,14 @@ "node": ">=6.9.0" } }, + "node_modules/@buttercup/fetch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@buttercup/fetch/-/fetch-0.1.2.tgz", + "integrity": "sha512-mDBtsysQ0Gnrp4FamlRJGpu7HUHwbyLC4uUav1I7QAqThFAa/4d1cdZCxrV5gKvh6zO1fu95bILNJi4Y2hALhQ==", + "optionalDependencies": { + "node-fetch": "^3.3.0" + } + }, "node_modules/@es-joy/jsdoccomment": { "version": "0.39.4", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.39.4.tgz", @@ -881,38 +891,6 @@ "node": ">=8" } }, - "node_modules/@jest/environment": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", - "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", - "dev": true, - "dependencies": { - "@jest/fake-timers": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/node": "*", - "jest-mock": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", - "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.1", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/@jest/schemas": { "version": "29.6.0", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", @@ -925,93 +903,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/types": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", - "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/types/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/types/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -1685,24 +1576,6 @@ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, - "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, "node_modules/@susnux/nextcloud-vite-config": { "version": "1.0.0-beta.16", "resolved": "https://registry.npmjs.org/@susnux/nextcloud-vite-config/-/nextcloud-vite-config-1.0.0-beta.16.tgz", @@ -1734,6 +1607,8 @@ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">= 10" } @@ -1774,30 +1649,6 @@ "@types/estree": "*" } }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, "node_modules/@types/jquery": { "version": "3.5.16", "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.16.tgz", @@ -1806,17 +1657,6 @@ "@types/sizzle": "*" } }, - "node_modules/@types/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" - } - }, "node_modules/@types/json-schema": { "version": "7.0.12", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", @@ -1855,33 +1695,6 @@ "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "node_modules/@types/tough-cookie": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", - "dev": true - }, - "node_modules/@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", @@ -2500,7 +2313,9 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/acorn": { "version": "8.10.0", @@ -2519,6 +2334,8 @@ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "acorn": "^8.1.0", "acorn-walk": "^8.0.2" @@ -2548,6 +2365,8 @@ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "debug": "4" }, @@ -2785,7 +2604,9 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/available-typed-arrays": { "version": "1.0.5", @@ -2802,8 +2623,12 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base-64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", + "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==" }, "node_modules/base64-js": { "version": "1.5.1", @@ -2886,6 +2711,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, + "peer": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -3135,6 +2961,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/byte-length/-/byte-length-1.0.2.tgz", + "integrity": "sha512-ovBpjmsgd/teRmgcPh23d4gJvxDoXtAzEL9xTfMU8Yc2kqCDb7L9jAG0XHl1nzuGl+h3ebCIF1i62UFyA9V/2Q==" + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -3219,6 +3050,14 @@ "node": ">=4" } }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "engines": { + "node": "*" + } + }, "node_modules/check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -3269,21 +3108,6 @@ "node": ">= 6" } }, - "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, "node_modules/cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -3323,6 +3147,8 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -3473,6 +3299,14 @@ "node": ">= 8" } }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "engines": { + "node": "*" + } + }, "node_modules/crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -3512,13 +3346,17 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/cssstyle": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "cssom": "~0.3.6" }, @@ -3530,18 +3368,31 @@ "version": "0.3.8", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/csstype": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "optional": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/data-urls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "abab": "^2.0.6", "whatwg-mimetype": "^3.0.0", @@ -3578,7 +3429,9 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/deep-eql": { "version": "4.1.3", @@ -3796,6 +3649,8 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.4.0" } @@ -3879,6 +3734,8 @@ "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "webidl-conversions": "^7.0.0" }, @@ -3937,6 +3794,8 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.12" }, @@ -4112,6 +3971,8 @@ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -4133,6 +3994,8 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=4.0" } @@ -4843,6 +4706,8 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "optional": true, + "peer": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -4928,6 +4793,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -5024,6 +4890,27 @@ "dev": true, "peer": true }, + "node_modules/fast-xml-parser": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.6.tgz", + "integrity": "sha512-Xo1qV++h/Y3Ng8dphjahnYe+rGHaaNdsYOBWL9Y9GCPKpNKilJtilvWkLcI9f9X2DoKTLsZsGYAls5+JL5jfLA==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -5034,6 +4921,29 @@ "reusify": "^1.0.4" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "optional": true, + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -5052,6 +4962,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, + "peer": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -5110,6 +5021,8 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -5119,6 +5032,18 @@ "node": ">= 6" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "optional": true, + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -5507,7 +5432,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, "bin": { "he": "bin/he" } @@ -5523,11 +5447,18 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/hot-patcher": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hot-patcher/-/hot-patcher-2.0.1.tgz", + "integrity": "sha512-ECg1JFG0YzehicQaogenlcs2qg6WsXQsxtnbr1i696u5tLUjtJdQAh0u2g0Q5YV45f263Ta1GnUJsc8WIfJf4Q==" + }, "node_modules/html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "whatwg-encoding": "^2.0.0" }, @@ -5546,6 +5477,8 @@ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -5566,7 +5499,9 @@ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, - "dependencies": { + "optional": true, + "peer": true, + "dependencies": { "agent-base": "6", "debug": "4" }, @@ -5589,6 +5524,8 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -5774,6 +5711,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "node_modules/is-builtin-module": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", @@ -5942,6 +5884,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "peer": true, "engines": { "node": ">=0.12.0" } @@ -5976,7 +5919,9 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/is-reference": { "version": "1.2.1", @@ -6229,224 +6174,6 @@ "node": ">=8" } }, - "node_modules/jest-environment-jsdom": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.6.1.tgz", - "integrity": "sha512-PoY+yLaHzVRhVEjcVKSfJ7wXmJW4UqPYNhR05h7u/TK0ouf6DmRNZFBL/Z00zgQMyWGMBXn69/FmOvhEJu8cIw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/jsdom": "^20.0.0", - "@types/node": "*", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1", - "jsdom": "^20.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jest-message-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", - "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-message-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-message-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-message-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-mock": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", - "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.1", - "@types/node": "*", - "jest-util": "^29.6.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", - "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jju": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", @@ -6487,6 +6214,8 @@ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "abab": "^2.0.6", "acorn": "^8.8.1", @@ -6594,6 +6323,11 @@ "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", "dev": true }, + "node_modules/layerr": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/layerr/-/layerr-0.1.2.tgz", + "integrity": "sha512-ob5kTd9H3S4GOG2nVXyQhOu9O8nBgP555XxWPkJI0tR0JeRilfyTp8WtPdIJHLXBmHMSdEq5+KMxiYABeScsIQ==" + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6722,6 +6456,16 @@ "node": ">= 12" } }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -6755,6 +6499,7 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, + "peer": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" @@ -6787,6 +6532,8 @@ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">= 0.6" } @@ -6796,6 +6543,8 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -6923,6 +6672,48 @@ "dev": true, "peer": true }, + "node_modules/nested-property": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nested-property/-/nested-property-4.0.0.tgz", + "integrity": "sha512-yFehXNWRs4cM0+dz7QxCd06hTbWbSkV0ISsqBfkntU6TOY4Qm3Q88fRRLOddkGh2Qq6dZvnKVAahfhjcUvLnyA==" + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "optional": true, + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "optional": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/node-gettext": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/node-gettext/-/node-gettext-3.0.0.tgz", @@ -7033,7 +6824,9 @@ "version": "2.2.7", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/object-inspect": { "version": "1.12.3", @@ -7253,6 +7046,8 @@ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "entities": "^4.4.0" }, @@ -7300,6 +7095,11 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-posix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz", + "integrity": "sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==" + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -7459,7 +7259,9 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/public-encrypt": { "version": "4.0.3", @@ -7517,8 +7319,7 @@ "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -7624,8 +7425,7 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "node_modules/resolve": { "version": "1.22.2", @@ -7984,6 +7784,8 @@ "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "xmlchars": "^2.2.0" }, @@ -8086,6 +7888,7 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "peer": true, "engines": { "node": ">=8" } @@ -8178,27 +7981,6 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -8346,6 +8128,11 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -8374,7 +8161,9 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/synckit": { "version": "0.8.5", @@ -8507,6 +8296,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "peer": true, "dependencies": { "is-number": "^7.0.0" }, @@ -8519,6 +8309,8 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -8534,6 +8326,8 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "punycode": "^2.1.1" }, @@ -8788,6 +8582,8 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">= 4.0.0" } @@ -8851,11 +8647,15 @@ "qs": "^6.11.0" } }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, "node_modules/url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -9700,6 +9500,8 @@ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "xml-name-validator": "^4.0.0" }, @@ -9707,11 +9509,64 @@ "node": ">=14" } }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "optional": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/webdav": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/webdav/-/webdav-5.2.3.tgz", + "integrity": "sha512-u5wqJULZhB7IwO3qVD9r0ikt6SMHZ4P4YYtLJ6JrCmSoZuW6KvanXWJAA4LZDm548lK7aCNUsy0VxbBKBXAGrg==", + "dependencies": { + "@buttercup/fetch": "^0.1.1", + "base-64": "^1.0.0", + "byte-length": "^1.0.2", + "fast-xml-parser": "^4.2.4", + "he": "^1.2.0", + "hot-patcher": "^2.0.0", + "layerr": "^0.1.2", + "md5": "^2.3.0", + "minimatch": "^5.1.0", + "nested-property": "^4.0.0", + "path-posix": "^1.0.0", + "url-join": "^4.0.1", + "url-parse": "^1.5.10" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/webdav/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/webdav/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=12" } @@ -9721,6 +9576,8 @@ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "iconv-lite": "0.6.3" }, @@ -9733,6 +9590,8 @@ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=12" } @@ -9742,6 +9601,8 @@ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "tr46": "^3.0.0", "webidl-conversions": "^7.0.0" @@ -9829,6 +9690,8 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=10.0.0" }, @@ -9850,6 +9713,7 @@ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", "dev": true, + "peer": true, "engines": { "node": ">=12" } @@ -9858,7 +9722,9 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/xtend": { "version": "4.0.2", diff --git a/package.json b/package.json index abb0d391..9b228768 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "@susnux/nextcloud-vite-config": "^1.0.0-beta.16", "@types/node": "^20.4.5", "@vitest/coverage-istanbul": "^0.33.0", - "jest-environment-jsdom": "^29.6.1", + "fast-xml-parser": "^4.2.6", "rollup": "^3.26.3", "tslib": "^2.6.1", "typedoc": "^0.24.8", @@ -71,6 +71,8 @@ "dependencies": { "@nextcloud/auth": "^2.1.0", "@nextcloud/l10n": "^2.2.0", - "@nextcloud/logger": "^2.5.0" + "@nextcloud/logger": "^2.5.0", + "@nextcloud/router": "^2.1.2", + "webdav": "^5.2.3" } } diff --git a/window.d.ts b/window.d.ts index a51440b8..626d2850 100644 --- a/window.d.ts +++ b/window.d.ts @@ -1,14 +1,17 @@ /// -import { FileAction } from './lib/fileAction' -import { NewFileMenu } from './lib/newFileMenu' +import type { FileAction } from './lib/fileAction' +import type { NewFileMenu } from './lib/newFileMenu' +import type { DavProperty } from './lib/dav/davProperties' export {} declare global { - interface Window { - OC: Nextcloud.v25.OC | Nextcloud.v26.OC | Nextcloud.v27.OC; - _nc_newfilemenu: NewFileMenu | undefined; - _nc_fileactions: FileAction[] | undefined; - } + interface Window { + OC: Nextcloud.v25.OC | Nextcloud.v26.OC | Nextcloud.v27.OC; + _nc_newfilemenu?: NewFileMenu + _nc_fileactions?: FileAction[] + _nc_dav_properties?: string[] + _nc_dav_namespaces?: DavProperty + } }