UNPKG

sardines-built-in-services

Version:
119 lines (109 loc) 4.16 kB
import { utils } from 'sardines-core' import { StorageBase } from './base' import * as fs from 'fs' import * as path from 'path' import * as proc from 'process' import { Stream } from 'stream'; export interface FileStorageSettings { root: string } export interface FileObject { path?: string content?: string stream?: Stream } export enum FileStorageReturnType { path = 'path', content = 'content', stream = 'stream' } export interface FileIdentity { name: string subId?: FileIdentity returnType?: FileStorageReturnType } export const parsePathIntoFileIdentity = (filepath: string): FileIdentity|null => { let id: FileIdentity|null = null if (!filepath || filepath === '/') return null let subdirs = (filepath[0] === '/' ? filepath.substr(1) : filepath).split('/') let pre: FileIdentity|null = id for (let item of subdirs) { if (!id) { id = {name: item} pre = id! } else { pre!.subId = {name: item} pre = pre!.subId } } return id! } export const parseFileIdentityIntoPath = (identity: FileIdentity): string => { let result = '' let pre = identity result += '/' + pre.name while (pre.subId) { pre = pre.subId result += '/' + pre.name } return result } const mkdir = (dir: string) => { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, {recursive: true}) } else if (!fs.lstatSync(dir).isDirectory()) { throw utils.unifyErrMesg(`Invalid file storage directory ${dir}`, 'storage', 'file') } } export class FileStorage extends StorageBase { private root: string constructor(settings: FileStorageSettings) { super() this.root = path.resolve(proc.cwd(), settings.root) mkdir(this.root) } async get(tableName: string, identity: FileIdentity): Promise<FileObject|null> { let result: FileObject|null = null const baseDir = path.resolve(this.root, tableName?`./${tableName}`:'') if (!fs.existsSync(baseDir) || !fs.lstatSync(baseDir).isDirectory()) { throw utils.unifyErrMesg(`table ${tableName} does not exist`, 'storage', 'file') } const filepath = path.resolve(baseDir, './' + (typeof identity === 'string'? identity:parseFileIdentityIntoPath(identity))) if (!fs.existsSync(filepath) || !fs.lstatSync(filepath).isFile()) { // throw utils.unifyErrMesg(`invalid file identity`, 'storage', 'file') return result } const returnType: FileStorageReturnType = identity.returnType ? identity.returnType : FileStorageReturnType.content switch(returnType) { case FileStorageReturnType.content: result = { content: fs.readFileSync(filepath, {encoding: 'utf8'}) } break case FileStorageReturnType.path: result = {path: filepath} break case FileStorageReturnType.stream: result = { stream: fs.createReadStream(filepath, {encoding: 'utf8'}) } break default: break } return result } async set(tableName: string, obj: FileObject|null, identity: FileIdentity|string) { const baseDir = path.resolve(this.root, tableName?`./${tableName}`:'') mkdir(baseDir) const filepath = path.resolve(baseDir, './' + (typeof identity === 'string'? identity:parseFileIdentityIntoPath(identity))) if (!obj && fs.existsSync(filepath)) fs.unlinkSync(filepath) else if (obj && obj.content) { fs.writeFileSync(filepath, obj.content, {encoding: 'utf8'}) } else if (obj && obj.path && fs.existsSync(obj.path) && fs.lstatSync(obj.path).isFile()) { fs.createReadStream(obj.path, {encoding: 'utf8'}).pipe(fs.createWriteStream(filepath, {encoding: 'utf8', autoClose: true})) } else if (obj && obj.stream) { obj.stream.pipe(fs.createWriteStream(filepath, {encoding: 'utf8', autoClose: true})) } } }