import { ExposeProvider } from './classes.exposeprovider.js'; import type { SmartExpose } from './classes.smartexpose.js'; import * as plugins from './plugins.js'; export interface IWebdavExposeProviderOptions { webdavCredentials: plugins.smartwebdav.IWebdavClientOptions; webdavSubPath: string; } export class WebDavExposeProvider extends ExposeProvider { public smartExposeRef: SmartExpose; public webdavClient: plugins.smartwebdav.WebdavClient; public options: IWebdavExposeProviderOptions; constructor(smartexposeRefArg: SmartExpose, optionsArg: IWebdavExposeProviderOptions) { super(); this.smartExposeRef = smartexposeRefArg; this.options = optionsArg; } public async houseKeeping(): Promise { const directoryContents = await this.webdavClient.listDirectory(this.options.webdavSubPath); for (const fileStat of directoryContents) { // lets read the meta.json file if (fileStat.filename.endsWith('.json')) { } } } public async getFilePathById(idArg: string): Promise { return plugins.smartpath.join(this.options.webdavSubPath, idArg); } public async ensureBaseDir(): Promise { await this.webdavClient.ensureDirectory(this.options.webdavSubPath); } public async start(): Promise { this.webdavClient = new plugins.smartwebdav.WebdavClient(this.options.webdavCredentials); await this.ensureBaseDir(); await this.houseKeeping(); this.smartExposeRef.taskmanager.addAndScheduleTask( new plugins.taskbuffer.Task({ name: 'webdavHousekeeping', taskFunction: async () => { await this.houseKeeping(); }, }), '0 * * * * *' ); } public async stop(): Promise { // Nothing to do here } public async exposeFile( optionsArg: Parameters[0] ): Promise<{ url: string; id: string; status: 'created' | 'updated' }> { await this.ensureBaseDir(); const fileId = plugins.smartunique.shortId(30); console.log( `Expsing file under id: ${fileId}. (${plugins.smartformat.prettyBytes( optionsArg.smartFile.contents.length )})` ); const webdavFilePath = await this.getFilePathById(fileId); const fileToUpload = await plugins.smartfile.SmartFile.fromBuffer( webdavFilePath, optionsArg.smartFile.contents ); await this.webdavClient.uploadSmartFileArray([fileToUpload]); console.log(`checking file presence: ${webdavFilePath}`); const existsOnWebdav = await this.webdavClient.wdClient.exists(webdavFilePath); const publicUrl = plugins.smartpath.join( this.smartExposeRef.options.exposedBaseUrl, webdavFilePath ); console.log(`cehcking for file at ${publicUrl}`); const response = await plugins.smartrequest.getBinary(publicUrl); plugins.smartexpect.expect(response.body).toEqual(fileToUpload.contents); if (optionsArg.deleteAfterMillis) { console.log( `Scheduling deletion of file with id: ${fileId} in ${optionsArg.deleteAfterMillis}ms...` ); plugins.smartdelay.delayFor(optionsArg.deleteAfterMillis).then(() => { console.log(`Deleting file with id: ${fileId}...`); this.deleteFileById(fileId); console.log(`Deleted file with id: ${fileId}`); }); } return { url: publicUrl, id: fileId, status: 'created', }; } public async exposeFileArray(optionsArg: Parameters[0]) { const returnArray = []; for (const smartFile of optionsArg.smartFiles) { returnArray.push( await this.exposeFile({ smartFile, deleteAfterMillis: optionsArg.deleteAfterMillis, privateUrl: optionsArg.privateUrl, }) ); } return returnArray; } public async wipeAll(): Promise<{ id: string; status: 'deleted' | 'failed' | 'notfound' }[]> { const directoryContents = await this.webdavClient.listDirectory(this.options.webdavSubPath); await this.webdavClient.ensureEmptyDirectory(this.options.webdavSubPath); return directoryContents.map((contentArg) => { return { id: contentArg.filename, status: 'deleted', }; }); } public async deleteFileById( idArg: string ): Promise<{ id: string; status: 'deleted' | 'failed' | 'notfound' }> { const filePath = await this.getFilePathById(idArg); if (!this.webdavClient.wdClient.exists(filePath)) { return { id: idArg, status: 'notfound', }; } await this.webdavClient.deleteFile(filePath); return { id: idArg, status: 'deleted', }; } }