Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chore: Migrate jsdoc to typescript in services and utils
Signed-off-by: Louis Chemineau <[email protected]>
  • Loading branch information
artonge authored and susnux committed Apr 23, 2025
commit cf32d1abe8b10aa70c01c8ead8af7121409bbef3
11 changes: 10 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,14 @@ module.exports = {
],
globals: {
appName: true,
}
},
overrides: [
{
files: ['*.ts'],
rules: {
'jsdoc/require-jsdoc': 'off',
'jsdoc/require-param': 'off',
},
},
],
}
19 changes: 7 additions & 12 deletions src/services/AlbumContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,29 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import axios from '@nextcloud/axios'
import axios, { type AxiosRequestConfig } from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
import { genFileInfo, encodeFilePath } from '../utils/fileUtils.js'
import { genFileInfo, encodeFilePath, type PhotoNode } from '../utils/fileUtils.js'
import allowedMimes from './AllowedMimes.js'
import { getCurrentUser } from '@nextcloud/auth'

/**
* List files from a folder and filter out unwanted mimes
*
* @param {string} path the path relative to the user root
* @param {object} [options] optional options for axios
* @param {boolean} [options.shared] fetch shared albums ?
* @return {Promise<object[]>} the file list
*/
export default async function(path = '/', options = {}) {
export default async function(path: string = '/', options: AxiosRequestConfig & { shared?: 'shared' | 'album' } = {}) {
const endpoint = generateUrl(`/apps/photos/api/v1/${options.shared ? 'shared' : 'albums'}`)
const prefix = `/files/${getCurrentUser()?.uid}`

// fetch listing
const response = await axios.get(endpoint + encodeFilePath(path), options)
const list = response.data
const list: PhotoNode[] = response.data
.map(data => ({ ...data, filename: `${prefix}${data.filename}` }))
.map(data => genFileInfo(data))

// filter all the files and folders
let folder = {}
const folders = []
const files = []
let folder: PhotoNode|undefined
const folders: PhotoNode[] = []
const files: PhotoNode[] = []

for (const entry of list) {
// is this the current provided path ?
Expand Down
97 changes: 36 additions & 61 deletions src/services/Albums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,30 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import type { FileStat, ResponseDataDetailed, StatOptions, WebDAVClient } from 'webdav'

import moment from '@nextcloud/moment'
import { translate as t } from '@nextcloud/l10n'

import logger from '../services/logger.js'
import { genFileInfo } from '../utils/fileUtils.js'
import { genFileInfo, type PhotoNode } from '../utils/fileUtils.js'
import { davClient } from './DavClient.ts'
import { getPropFind } from './DavRequest.ts'
import type { RawCollection } from './collectionFetcher.ts'

type Album = PhotoNode & {
id: string // The id of the album.
name: string // The name of the album.
creationDate: number // The creation date of the album.
isShared: string // Whether the current user as shared the album.
isCollaborative: string // Whether the album can be edited by other users.
itemCount: number // The number of item in the album.
cover: number // The cover of the album.
collaborators: object[] // The list of collaborators.
date: string // The date of the album.
}

/**
* @typedef {object} Album
* @property {string} id - The id of the album.
* @property {string} name - The name of the album.
* @property {number} creationDate - The creation date of the album.
* @property {string} isShared - Whether the current user as shared the album.
* @property {string} isCollaborative - Whether the album can be edited by other users.
* @property {number} itemCount - The number of item in the album.
* @property {number} cover - The cover of the album.
*/

/**
* @param {string} extraProps - Extra properties to add to the DAV request.
* @return {string}
*/
function getDavRequest(extraProps = '') {
function getDavRequest(extraProps: string = ''): string {
return `<?xml version="1.0"?>
<d:propfind xmlns:d="DAV:"
xmlns:oc="http://owncloud.org/ns"
Expand All @@ -43,21 +43,13 @@ function getDavRequest(extraProps = '') {
</d:propfind>`
}

/**
*
* @param {string} path - Albums' root path.
* @param {import('webdav').StatOptions} options - Options to forward to the webdav client.
* @param {string} extraProps - Extra properties to add to the DAV request.
* @param {import('webdav').WebDAVClient} client - The DAV client to use.
* @return {Promise<Album|null>}
*/
export async function fetchAlbum(path, options, extraProps = '', client = davClient) {
export async function fetchAlbum(path: string, options: StatOptions, extraProps: string = '', client: WebDAVClient = davClient): Promise<Album|null> {
try {
const response = await client.stat(path, {
data: getDavRequest(extraProps),
details: true,
...options,
})
}) as ResponseDataDetailed<RawCollection>

logger.debug('[Albums] Fetched an album: ', { data: response.data })

Expand All @@ -71,21 +63,13 @@ export async function fetchAlbum(path, options, extraProps = '', client = davCli
}
}

/**
*
* @param {string} path - Albums' root path.
* @param {import('webdav').StatOptions} options - Options to forward to the webdav client.
* @param {string} extraProps - Extra properties to add to the DAV request.
* @param {import('webdav').WebDAVClient} client - The DAV client to use.
* @return {Promise<Album[]>}
*/
export async function fetchAlbums(path, options, extraProps = '', client = davClient) {
export async function fetchAlbums(path: string, options: StatOptions, extraProps: string = '', client: WebDAVClient = davClient): Promise<Album[]> {
try {
const response = await client.getDirectoryContents(path, {
data: getDavRequest(extraProps),
details: true,
...options,
})
}) as ResponseDataDetailed<Array<RawCollection>>

logger.debug(`[Albums] Fetched ${response.data.length} albums: `, { data: response.data })

Expand All @@ -101,28 +85,26 @@ export async function fetchAlbums(path, options, extraProps = '', client = davCl
}
}

/**
*
* @param {object} album - An album received from a webdav request.
* @return {Album}
*/
function formatAlbum(album) {
function formatAlbum(rawAlbum: RawCollection): Album {
let collaborators: object[] = []

// Ensure that we have a proper collaborators array.
if (album.props.collaborators === '') {
album.props.collaborators = []
} else if (typeof album.props.collaborators.collaborator === 'object') {
if (Array.isArray(album.props.collaborators.collaborator)) {
album.props.collaborators = album.props.collaborators.collaborator
if (rawAlbum.props.collaborators === '') {
collaborators = []
} else if (typeof rawAlbum.props.collaborators.collaborator === 'object') {
if (Array.isArray(rawAlbum.props.collaborators.collaborator)) {
collaborators = rawAlbum.props.collaborators.collaborator
} else {
album.props.collaborators = [album.props.collaborators.collaborator]
collaborators = [rawAlbum.props.collaborators.collaborator]
}
}

// Extract custom props.
album = genFileInfo(album)
const album = genFileInfo(rawAlbum) as Album
album.collaborators = collaborators

// Compute date range label.
const dateRange = JSON.parse(album.dateRange?.replace(/&quot;/g, '"') ?? '{}')
const dateRange = JSON.parse(rawAlbum.dateRange?.replace(/&quot;/g, '"') ?? '{}')
if (dateRange.start === null) {
dateRange.start = moment().unix()
dateRange.end = moment().unix()
Expand All @@ -140,26 +122,19 @@ function formatAlbum(album) {
return album
}

/**
*
* @param {string} path - Albums' root path.
* @param {import('webdav').StatOptions} options - Options to forward to the webdav client.
* @param {import('webdav').WebDAVClient} client - The DAV client to use.
* @return {Promise<Array>}
*/
export async function fetchAlbumContent(path, options, client = davClient) {
export async function fetchAlbumContent(path: string, options: StatOptions, client: WebDAVClient = davClient): Promise<PhotoNode[]> {
try {
const response = await client.getDirectoryContents(path, {
data: getPropFind(),
details: true,
...options,
})
}) as ResponseDataDetailed<Array<FileStat>>

const fetchedFiles = response.data
.map(file => genFileInfo(file))
.filter(file => file.fileid)

logger.debug(`[Albums] Fetched ${fetchedFiles.length} new files: `, fetchedFiles)
logger.debug(`[Albums] Fetched ${fetchedFiles.length} new files: `, { fetchedFiles })

return fetchedFiles
} catch (error) {
Expand Down
6 changes: 3 additions & 3 deletions src/services/AllowedMimes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

import { loadState } from '@nextcloud/initial-state'

const imageMimes = loadState('photos', 'image-mimes')
const videoMimes = loadState('photos', 'video-mimes')
const allMimes = [...imageMimes, ...videoMimes]
const imageMimes = loadState('photos', 'image-mimes', [])
const videoMimes = loadState('photos', 'video-mimes', [])
const allMimes = [...imageMimes, ...videoMimes] as string[]

export { allMimes as default, allMimes, imageMimes, videoMimes }
2 changes: 1 addition & 1 deletion src/services/AreTagsInstalled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@

import { loadState } from '@nextcloud/initial-state'

const systemtags = loadState('photos', 'systemtags')
const systemtags = loadState('photos', 'systemtags', false) as boolean
export default systemtags
3 changes: 0 additions & 3 deletions src/services/DavRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ export const getDefaultDavProps = () => {
return props
}

/**
* @param extraProps - Extra properties to add to the DAV request.
*/
export function getPropFind(extraProps: string[] = []): string {
return `<?xml version="1.0"?>
<d:propfind xmlns:d="DAV:"
Expand Down
2 changes: 1 addition & 1 deletion src/services/IsAppStoreEnabled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@

import { loadState } from '@nextcloud/initial-state'

const appStoreEnabled = loadState('photos', 'appStoreEnabled')
const appStoreEnabled = loadState('photos', 'appStoreEnabled', false) as boolean
export default appStoreEnabled
2 changes: 1 addition & 1 deletion src/services/IsMapsInstalled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@

import { loadState } from '@nextcloud/initial-state'

const maps = loadState('photos', 'maps')
const maps = loadState('photos', 'maps', false) as boolean
export default maps
2 changes: 1 addition & 1 deletion src/services/IsRecognizeInstalled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@

import { loadState } from '@nextcloud/initial-state'

const recognize = loadState('photos', 'recognize')
const recognize = loadState('photos', 'recognize', false) as boolean
export default recognize
Loading