| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859 |
- import { StorageAdapter, SavedPath } from '../types';
- import { pipeline } from 'stream/promises';
- import * as fs from 'fs';
- import { mkdir, rename, unlink } from 'fs/promises';
- import * as path from 'path';
- const DEFAULT_LOCAL_ROOT = '/data/media';
- export class LocalStorageAdapter implements StorageAdapter {
- constructor(private readonly localRoot: string = DEFAULT_LOCAL_ROOT) {}
- private resolveAbsolutePath(
- localStoragePrefix: string,
- relativePath: string,
- ) {
- return path.resolve(this.localRoot, localStoragePrefix, relativePath);
- }
- private tempPath(targetPath: string) {
- return `${targetPath}.part`;
- }
- async put(
- relativePath: string,
- localStoragePrefix: string,
- stream: NodeJS.ReadableStream,
- ): Promise<{ savedPath: SavedPath }> {
- const targetPath = this.resolveAbsolutePath(
- localStoragePrefix,
- relativePath,
- );
- const targetDir = path.dirname(targetPath);
- await mkdir(targetDir, { recursive: true });
- const stagingPath = this.tempPath(targetPath);
- const writeStream = fs.createWriteStream(stagingPath, { flags: 'w' });
- try {
- await pipeline(stream, writeStream);
- await rename(stagingPath, targetPath);
- return { savedPath: targetPath };
- } catch (err) {
- await unlink(stagingPath).catch(() => undefined);
- throw err;
- }
- }
- async delete(
- relativePath: string[],
- localStoragePrefix: string,
- ): Promise<void> {
- for (const relative of relativePath) {
- const targetPath = this.resolveAbsolutePath(localStoragePrefix, relative);
- await unlink(targetPath).catch((err) => {
- if (err.code !== 'ENOENT') {
- throw err;
- }
- });
- }
- }
- }
|