85 lines
2.0 KiB
TypeScript
85 lines
2.0 KiB
TypeScript
import { cuid } from '@adonisjs/core/helpers'
|
|
import { posix } from 'node:path'
|
|
|
|
export interface FileNameMeta {
|
|
name: string
|
|
ext: string
|
|
}
|
|
|
|
export interface UniqueNameFormatterParams {
|
|
base: string
|
|
count: number
|
|
extension: string
|
|
}
|
|
|
|
export type UniqueNameFormatter = (params: UniqueNameFormatterParams) => string
|
|
|
|
export default class PathService {
|
|
public toStoragePath(path: string = ''): string {
|
|
let safePath = path.replace(/^(\.\.(\/|\\|$))+/, '')
|
|
safePath = safePath.startsWith('/') ? safePath.slice(1) : safePath
|
|
|
|
return safePath
|
|
}
|
|
|
|
public toClientPath(path: string = ''): string {
|
|
return path.replace(/^\/?uploads\//, '/')
|
|
}
|
|
|
|
public join(...parts: string[]): string {
|
|
return posix.join(...parts)
|
|
}
|
|
|
|
public dirname(path: string): string {
|
|
return this.toStoragePath(path).split('/').slice(0, -1).join('/')
|
|
}
|
|
|
|
public basename(path: string): string {
|
|
return path.split('/').reverse()[0]
|
|
}
|
|
|
|
public getFileNameMeta(name: string): FileNameMeta {
|
|
const extIndex = name.lastIndexOf('.')
|
|
const rawName = extIndex !== -1 ? name.slice(0, extIndex) : name
|
|
const ext = extIndex !== -1 ? name.slice(extIndex).trim() : ''
|
|
|
|
return {
|
|
name: rawName,
|
|
ext,
|
|
}
|
|
}
|
|
|
|
public sanitizeFileName(name: string): string {
|
|
return name.replace(/[()]/g, '').replace(/[^a-zA-Z0-9.\-_ ]/g, '')
|
|
}
|
|
|
|
public async generateUniqueName(
|
|
dir: string,
|
|
fileName: string,
|
|
exists: (path: string) => Promise<boolean>,
|
|
formatter?: UniqueNameFormatter
|
|
): Promise<string> {
|
|
const { ext, name } = this.getFileNameMeta(fileName)
|
|
const safeBase = this.sanitizeFileName(name)
|
|
|
|
let counter = 1
|
|
let newName = `${safeBase}${ext}`
|
|
|
|
while (await exists(this.join(dir, newName))) {
|
|
newName =
|
|
typeof formatter === 'function'
|
|
? formatter({ base: safeBase, count: counter, extension: ext })
|
|
: `${safeBase}-${counter}${ext}`
|
|
|
|
counter++
|
|
|
|
if (counter > 5) {
|
|
newName = `${cuid()}${ext}`
|
|
break
|
|
}
|
|
}
|
|
|
|
return newName
|
|
}
|
|
}
|