diff --git a/packages/lib/services/rest/routes/notes.test.ts b/packages/lib/services/rest/routes/notes.test.ts index 4ad0a7b5b..7da72dab9 100644 --- a/packages/lib/services/rest/routes/notes.test.ts +++ b/packages/lib/services/rest/routes/notes.test.ts @@ -151,12 +151,13 @@ describe('routes/notes', () => { }); test('should not create resource from files that does not exist', async () => { - expect( - async () => createResourcesFromPaths([ - { originalUrl: 'not-a-real-file', path: '/does/not/exist' }, - ]), - ).rejects.toThrow('Cannot access /does/not/exist'); + Logger.globalLogger.enabled = false; + const result = await createResourcesFromPaths([ + { originalUrl: 'not-a-real-file', path: '/does/not/exist' }, + ]); + Logger.globalLogger.enabled = true; + expect(result[0].resource).toBe(null); const resources = await Resource.all(); expect(resources.length).toBe(0); }); @@ -173,4 +174,14 @@ describe('routes/notes', () => { expect(await Note.load(note2.id)).toBeFalsy(); }); + test('should not stop execution if a file can not be processed', async () => { + Logger.globalLogger.enabled = false; + const result = await createResourcesFromPaths([ + { originalUrl: 'asdf.png', path: `${__dirname}/bad-path-should-not-exist` }, + { originalUrl: 'asdf.png', path: `${__dirname}/../../../images/SideMenuHeader.png` }, + ]); + Logger.globalLogger.enabled = true; + + expect(result.length).toBe(2); + }); }); diff --git a/packages/lib/services/rest/routes/notes.ts b/packages/lib/services/rest/routes/notes.ts index 667c149b4..92a849f1b 100644 --- a/packages/lib/services/rest/routes/notes.ts +++ b/packages/lib/services/rest/routes/notes.ts @@ -29,6 +29,7 @@ const { ErrorNotFound } = require('../utils/errors'); import { fileUriToPath } from '@joplin/utils/url'; import { NoteEntity, ResourceEntity } from '../../database/types'; import { DownloadController } from '../../../downloadController'; +import { FetchBlobOptions } from '../../../types'; const logger = Logger.create('routes/notes'); @@ -68,11 +69,11 @@ type RequestNote = { stylesheets: any; }; -type FetchOptions = { +interface FetchOptions extends FetchBlobOptions { timeout?: number; maxRedirects?: number; downloadController?: DownloadController; -}; +} type DownloadedMediaFile = { @@ -80,7 +81,7 @@ type DownloadedMediaFile = { path: string; }; -interface ResourceFromPath extends DownloadedMediaFile { +export interface ResourceFromPath extends DownloadedMediaFile { resource: ResourceEntity; } @@ -315,20 +316,17 @@ async function downloadMediaFiles(urls: string[], fetchOptions?: FetchOptions, a } export async function createResourcesFromPaths(mediaFiles: DownloadedMediaFile[]) { - const resources: Promise[] = []; - - for (const mediaFile of mediaFiles) { + const processFile = async (mediaFile: DownloadedMediaFile) => { try { - resources.push( - shim.createResourceFromPath(mediaFile.path) - // eslint-disable-next-line - .then(resource => ({ ...mediaFile, resource })) - ); + const resource = await shim.createResourceFromPath(mediaFile.path); + return { ...mediaFile, resource }; } catch (error) { logger.warn(`Cannot create resource for ${mediaFile.originalUrl}`, error); + return { ...mediaFile, resource: null }; } - } + }; + const resources = mediaFiles.map(processFile); return Promise.all(resources); } diff --git a/packages/lib/shim-init-node.ts b/packages/lib/shim-init-node.ts index 8b0a9ab24..942b824be 100644 --- a/packages/lib/shim-init-node.ts +++ b/packages/lib/shim-init-node.ts @@ -9,9 +9,9 @@ import * as fs from 'fs-extra'; import * as pdfJsNamespace from 'pdfjs-dist'; import { writeFile } from 'fs/promises'; import { ResourceEntity } from './services/database/types'; -import { DownloadController } from './downloadController'; import { TextItem } from 'pdfjs-dist/types/src/display/api'; import replaceUnsupportedCharacters from './utils/replaceUnsupportedCharacters'; +import { FetchBlobOptions } from './types'; import FileApiDriverLocal from './file-api-driver-local'; const mimeUtils = require('./mime-utils.js').mime; @@ -27,16 +27,6 @@ const dgram = require('dgram'); // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied const proxySettings: any = {}; -type FetchBlobOptions = { - path?: string; - method?: string; - maxRedirects?: number; - timeout?: number; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - headers?: any; - downloadController?: DownloadController; -}; - function fileExists(filePath: string) { try { return fs.statSync(filePath).isFile(); diff --git a/packages/lib/types.ts b/packages/lib/types.ts index 1a8338fdf..3a72c6551 100644 --- a/packages/lib/types.ts +++ b/packages/lib/types.ts @@ -1,3 +1,5 @@ +import { DownloadController } from './downloadController'; + export enum ApplicationPlatform { Unknown = 0, Windows = 1, @@ -13,3 +15,12 @@ export enum ApplicationType { Mobile = 2, Cli = 3, } + +export type FetchBlobOptions = { + path?: string; + method?: string; + maxRedirects?: number; + timeout?: number; + headers?: Record; + downloadController?: DownloadController; +};