Skip to content

Latest commit

 

History

History
270 lines (251 loc) · 8.79 KB

Filepath.md

File metadata and controls

270 lines (251 loc) · 8.79 KB
// how to import into your own code
import { Filepath } from "@safelytyped/filepath";

// our base class and interface can be found here:
import { RefinedString, Value } from "@safelytyped/core-types";

/**
 * `Filepath` is a safe type. It represents a path to an item on
 * a (possibly local) filesystem.
 *
 * It acts as a wrapper around NodeJS's `path` module.
 *
 * @category Filepath
 */
export class Filepath extends RefinedString implements Value<string> {

    /**
     * `Constructor` creates a new `Filepath`.
     *
     * @param input
     * The data we need to build a Filepath.
     * @param onError
     * If `input` fails validation, we pass an {@link AppError}
     * to `onError()`.
     * @param base
     * Use this to keep track of a parent path of some kind.
     * @param pathApi
     * Use this if you want to pass in your own implementation (e.g. for
     * unit testing)
     */
    public constructor(
        input: string,
        {
            onError = THROW_THE_ERROR,
            pathApi = path,
            base
        }: Partial<MakeFilepathOptions> = {}
    );

    /**
     * `base` is for keeping track of any path that this Filepath
     * is built from, relative to, and the like.
     *
     * Useful for tracking parent paths when resolving '$ref' entries
     * in JSON schema and the like.
     */
    public readonly base: string;

    /**
     * `pathApi` is the API to use for all path operations.
     *
     * By default, this is the Node JS `path` module for your platform
     * (`path.windows` or `path.posix`).
     */
    public readonly pathApi: string;

    // =======================================================================
    //
    // pathApi wrappers
    //
    // -----------------------------------------------------------------------

    /**
     * `basename()` is a wrapper around NodeJS's `path.basename()`.
     *
     * `basename` returns the last portion of a path, similar to the Unix
     * `basename` command. Trailing directory separators are ignored,
     * see {@link PathApi.sep}.
     *
     * @param ext
     * An optional file extension to strip (if present).
     * @returns
     * The last portion of the Filepath. If the Filepath` ends in `ext`,
     * that is stripped too.
     */
    public basename(ext?: string): string;

    /**
     * `dirname()` is a wrapper around NodeJS's `path.dirname()`.
     *
     * The returned Filepath will have the same `base` path and
     * same `pathApi` that this Filepath does.
     *
     * `dirname()` returns the directory name of `path`, similiar to
     * the UNIX `dirname` command. Trailing directory separators are
     * ignored, see {@link PathApi.sep}
     *
     * @returns
     * Everything but the last portion of `path`.
     */
    public dirname(
        {
            onError = THROW_THE_ERROR,
            pathApi = this.#_pathApi,
            base = this.#_base
        }: Partial<MakeFilepathOptions> = {}
    ): Filepath;

    /**
     * `extname` is a wrapper around NodeJS's `path.extname()`.
     *
     * `extname()` returns the extension of the Filepath, from the last
     * occurance of the `.` character in the last segment of the path to
     * the end of the string.
     *
     * If there is no `.` in the last segment of the path, or if the only
     * `.` character is the first character of the last segment (ie a
     * UNIX dotfile with no extension), an empty string is returned.
     *
     * @returns
     * - the file extension (starting with a `.`) on success
     * - an empty string otherwise
     */
    public extname(): string;

    /**
     * `isAbsolute()` is a wrapper around NodeJS's `path.isAbsolute()`.
     *
     * `isAbsolute()` determines if this Filepath is an absolute path or not.
     *
     * An absolute path is a path that starts with a filesystem root
     * segment. Absolute paths are the opposite of relative paths: they
     * don't rely on the current working directory.
     *
     * @returns
     * - `true` if this Filepath is an absolute path.
     * - `false` if this Filepath is a relative path.
     */
    public isAbsolute(): boolean;

    /**
     * `join()` is a wrapper around NodeJS's `path.join()`.
     *
     * `join()` combines this Filepath and all the given segments into a
     * single string, using {@link PathApi.sep} as the delimiter, and then
     * normalises that string.
     *
     * Zero-length path segments are ignored.
     *
     * If the normalised string is empty, `join()` returns `.` (the
     * current working directory).
     *
     * The returned Filepath will have the same `base` path and
     * same `pathApi` that this Filepath does.
     *
     * @returns
     * The assembled path. Guaranteed never to be empty.
     */
    public join(...paths: string[]): Filepath;

    /**
     * `parse()` is a wrapper around NodeJS's `path.parse()`.
     *
     * `parse()` breaks down this Filepath into separate parts. Trailing
     * directory separators are ignored.
     *
     * The returned object can include any / all of:
     *
     * - `root`: the root of the filesystem, if the path is absolute
     * - `dir`: all the root and folder segments of the path
     * - `base`: the filename segment of the path
     * - `name`: the filename segment of the path, minus the extension
     * - `ext`: the extension segment of the path, starting with a `.`
     *
     * All of these are strings. Use {@link PathApi.format} to convert
     * this back into a single path string.
     *
     * @returns
     * The breakdown of this Filepath.
     */
    public parse(): path.ParsedPath;

    /**
     * `relative()` is a wrapper around NodeJS's `path.relative()`.
     *
     * `relative()` calculates a relative path between `from` and `to`.
     * `from` is this Filepath.
     *
     * If `from` and `to` point to the same path (after calling
     * {@link PathApi.resolve} on them both), and empty string is returned.
     *
     * @param to
     * Where do you want the relative path to go to?
     * @returns
     * - An empty string if `from` and `to` point to the same path.
     * - The relative path otherwise.
     */
    public relative(to: Filepath): string;

    /**
     * `resolve()` is a wrapper around NodeJS's `path.resolve()`.
     *
     * `resolve()` combines this Filepath and the given path segments into
     *  an absolute path.
     *
     * It works from right-to-left (from the last segment backwards), and
     * it stops as soon as an absolute path has been constructed.
     *
     * Zero-length path segments are ignored.
     *
     * If the assembled path is a relative path, it is treated as a relative
     * path to the current working directory, and converted into an
     * absolute path.
     *
     * The assembled path is normalised before being returned. Trailing
     * path separators are removed.
     *
     * If no path segments are passed in, `resolve()` returns the absolute
     * path of resolving `this.valueOf()` against `this.base`. It's
     * a good way to get the absolute path of this Filepath. If this Filepath
     * doesn't have a `base`, it uses the process's current working directory.
     *
     * The returned Filepath will have the same `base` path and
     * same `pathApi` that this Filepath does.
     *
     * @returns
     * The assembled, normalised Filepath. Guaranteed to be an absolute path.
     */
    public resolve(...paths: string[]): Filepath;

    /**
     * `toNamespacedPath()` is a wrapper around NodeJS's
     * `path.toNamespacedPath()`.
     *
     * `toNamespacedPath()` behaves differently on Windows and on POSIX.
     *
     * On Windows, it converts this Filepath to the equivalent namespace-prefixed
     * path: https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#namespaces.
     *
     * On POSIX, a new Filepath is returned, containing the unmodified
     * `Filepath.toValue()`.
     *
     * @returns
     * - on Windows, the namespaced path.
     * - on POSIX, the unmodified path.
     */
    public toNamespacedPath(): Filepath;

    // =======================================================================
    //
    // INHERITED METHODS
    //
    // -----------------------------------------------------------------------

    /**
     * `[Symbol.toPrimitive]()` supports Javascript auto-conversion to
     * a string or number.
     */
    public [ Symbol.toPrimitive ](hint: PrimitiveHint): string | number;

    /**
     * valueOf() returns the wrapped value.
     *
     * For types passed by reference, we do NOT return a clone of any kind.
     * You have to be careful not to accidentally change this value.
     *
     * @returns the data that is stored in this object.
     */
    public valueOf(): T {
        return this._value;
    }

    /**
     * implementsValue() is a helper method for the {@link isValue} type guard
     * function.
     */
    public implementsValue(): this is Value<T>;
}