"use strict";
/*
 * @adonisjs/drive
 *
 * (c) Harminder Virk <virk@adonisjs.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.PathPrefixer = void 0;
/// <reference path="../../adonis-typings/index.ts" />
const utils_1 = require("@poppinss/utils");
const path_1 = require("path");
const Exceptions_1 = require("../Exceptions");
/**
 * Path prefixer for resolving and prefixing paths for disk drivers
 */
class PathPrefixer {
    constructor(prefix = '') {
        /**
         * Separator used for dividing path segments is always unix-style forward slash
         */
        this.separator = '/';
        // strip slashes from the end of the prefix
        this.prefix = prefix.replace(/\/+$/g, '');
        // always end prefix with separator if it is not empty
        if (this.prefix !== '' || prefix === this.separator) {
            this.prefix += this.separator;
        }
    }
    /**
     * Normalize given path to always use `/` as separator and resolve relative paths using `.` and `..`.
     * It also guards against path traversal beyond the root.
     */
    normalizePath(path) {
        const converted = (0, utils_1.slash)(path);
        const parts = [];
        for (const part of converted.split(this.separator)) {
            if (['', '.'].includes(part)) {
                continue;
            }
            if (part === '..') {
                // if we are traversing beyond the root
                if (parts.length === 0) {
                    throw Exceptions_1.PathTraversalDetectedException.invoke(converted);
                }
                parts.pop();
            }
            else {
                parts.push(part);
            }
        }
        return parts.join(this.separator);
    }
    /**
     * Ruturns normalized and prefixed location path.
     */
    prefixPath(location) {
        return this.prefix + this.normalizePath(location);
    }
    /**
     * Ruturns normalized and prefixed location path for directory so always ending with slash.
     * Useful for cloud drivers prefix when listitng files.
     */
    prefixDirectoryPath(location) {
        return this.prefixPath(location) + this.separator;
    }
    /**
     * Returns normalized path after stripping the current prefix from it.
     * It is a reverse operation of `prefixPath`.
     */
    stripPrefix(location) {
        const path = (0, path_1.relative)(this.prefix, (0, utils_1.slash)(location));
        return this.normalizePath(path);
    }
    /**
     * Returns a new instance of `PathPrefixer` which is using as prefix stripped prefix from path of current `PathPrefixer`.
     */
    withStrippedPrefix(path) {
        return new PathPrefixer(this.stripPrefix(path));
    }
    /**
     * Returns a new instance of `PathPrefixer` which is using as prefix current prefix merged with provided prefix.
     */
    withPrefix(prefix) {
        return new PathPrefixer(this.prefixPath(prefix));
    }
    /**
     * Returns a new instance of `PathPrefixer` which is using as prefix provided normalized path.
     */
    static fromPath(path) {
        return new this((0, utils_1.slash)((0, path_1.normalize)(path)));
    }
}
exports.PathPrefixer = PathPrefixer;
