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: { smartFile: plugins.smartfile.SmartFile; deleteAfterMillis?: number; privateUrl?: boolean; }): 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 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', }; } }