Skip to content

Latest commit

 

History

History
264 lines (174 loc) · 10.8 KB

File metadata and controls

264 lines (174 loc) · 10.8 KB

filepath tokenizer

Synopsis

Part of the monorepo mangos

  • Tokenizes filepath string into its consituants;
  • Preserves correctly (node resolve does not) the root of dos device path and unc path.
  • Provides utilities to work with different path types irrespective of OS used.

Supported Paths

Node resolve does not preserve root of DOS Device Path

Note: \ needs to be escaped when using it in js code.

// node  
> path.resolve('\\\\?\\C:\\repos','../../../text.txt');
// -> \\?\text.txt  \\?\C: is mangled

// filePath
> fp.resolve('\\\\?\\C:\\repos','../../../text.txt').toString();
// -> '\\?\C:\text.txt'  aka'\\?\C:\' root is preserved

Node resolve does not (always) preserve root of UNC Path

Note: \ needs to be escaped when using it in js code.

// node resolve
path.resolve('//?/UNC/Server/share', '../../../txt');
// -> '\\\\?\\txt'  mangled unc loot

// this library
filePath.resolve('//?/UNC/Server/share', '../../../txt').toString();
// -> '\\\\?\\UNC\\Server\\share\\txt'  unc root preserved
// -> root: \\\\?\\UNC\\Server\\share

path.resolve('//system07/c$/x/y', '../../../../../txt');
// -> '\\\\system07\\c$\\txt' unc root preserved 

fp.resolve('//system07/c$/x/y', '../../../../../txt').toString()
// -> '\\\\system07\\c$\\txt' unc root is preserved

Api

Overview

There are 4 exported functions:

import { allPath, firstPath, resolve, resolvePathObject } from '@mangos/filepath';

There are 2 exported classes:

import { ParsedPath,  ParsedPathError, PathToken } from '@mangos/filepath';

There is 1 exported type:

import type { InferPathOptions } from '@mangos/filepath'

Most of the time you will be using resolve, firstPath.

Type InferPathOptions

The functions allPath and firstPath will try to tokenize a path string based on options object specified as the second argument.

type InferPathOptions = {
    devicePath: boolean; // parse string as dos device path
    unc: boolean; // parse string as unc path
    dos: boolean; // parse string as traditional dos path
    posix: boolean; // parse string as unix path
}

Multiple path types can be tokenized from the same path string.

The response of allPath will be an array of ParsedPath or/and ParsedPathError class instance, representing parsing for multiple OS path types.

defaults:

If InferpathOptions argument is left empty in allPath and firstPath the default will be used based on OS:

  • The default for windos: { dos: true, devicePath: true, unc: true, posix: false }
  • The default for unix: { posix: true }

ParsedPath object

The response of a successfull path tokenization will be an ADT: ParsedPath.

An instance of ParsedPath has the following fields/members

  • members:
    • toString(): string: return the original path string
    • isRelative(): boolean: is the a path a relative one?
  • fields:
    • type: string: one of the value devicePath, unc, dos, posix.
    • path: FileToken[]: the path tokenized (see source).

ParsedPathError object

If a path has illigal characters or is invalid the result of a tokenization will be an ADT: ParsedPathError

  • members:
    • toString(): string: algamation of all errors found during parsing.
  • attributes:
    • type: string: one of the values devicePath, unc, dos, posix.
    • path: FileToken[]: the path tokenized.

Path type order of evaluation

When a string is parsed it will be evaluated according to path types in the following order:

  1. devicePath tokanization will be tried first (if the devicePath boolean is set to true).
  2. unc tokanization will be tried second, (if the devicePath boolean is set to true).
  3. dos tokanization will be tried third, (if the dos boolean is set to true).
  4. posix tokanization will be tried forth, (if the posix boolean is set to true)

PathToken object

You dont create PathTokens yourself the api will do it for you.

class PathToken {
	value: string; // actual path fragment (directory, seperator, or file)
	start: number; // start location in the original string
	end: number; // end (inclusive) in the original string
    error?: string; // this token has invalid character for the OS selected
    isRoot(): boolean; // is this token a Root Token (c:/,  /, //?/UNC/Server/share, etc)
    isPathElement(): boolean; // a normal path element
    isCurrent(): boolean; // token representing "./"
    isParent(): boolean // token representing "../"
    isSeperator(): boolean // token representing "/" (posix) or "\" (windows, dos)
    hasError(): boolean // did tokenizing the path associated an error with this token
}

Functions

function: allPath

function allPath(path = '', options: InferPathOptions = {}): (ParsedPath | ParsedPathError)[];
Arguments:
  • path: string optional: (Default is current working directory). Relative or absolute path conforming to one of the supported path types.
  • options: InferPathOptions optional: Parsing limited to flags set to true in options.
Return:
Examples:
import { allPath  } from '@mangos/filepath';

// will attempt to tokenize the path according to dos and unc path types
const paths = allPath('//system07/c$/x/y', { dos: true, unc: true });

// unc is the only possible match
paths.length
// -> 1
paths[0].type
// -> unc
path[0].toString()
// -> \\system07\c$\x\y or '\\\\system07\\c$\\x\\y' with \ escaped

function: firstPath

function firstPath(path = '', options: InferPathOptions = {}): ParsedPath | ParsedPathError | undefined;
Arguments:
  • path: string optional: (Default is current working directory). Relative or absolute path conforming to one of the supported path types.
  • options: InferPathOptions optional: Parsing limited to flags set to true in options.
Return:
  • undefined: The path was not confirm to any of the types listed in path types

  • ParsedPath: In case of successfull parse.

  • ParsedPathError: In case of legal structure but illegal characters in the path.

function: resolvePathObject

function resolvePathObject(from: ParsedPath, ...toFragments: string[]): ParsedPath;
Arguments:
  • from: ParsedPath: A previously created ParsedPath object via firstPath function.
  • toFragments: string[]: A sequence of paths or path segments.
Return:
throws:
  • If from is a ParsedPathError an Error will be thrown.
  • If any of the toFragments is an invalid path an Error will be thrown.

function: resolve

function resolve(fromStr: string, ...toFragments: string[]): ParsedPath;
Arguments:
  • fromStr: string optional: A path according to a path type. Defaults to current working directory if absent/undefined.
  • toFragments: string[]: A sequence of paths or path segments.
Return:
throws:

If fromStr is invalid a ParsedPathError an Error will be thrown.

License

Copyright (c) 2019-2025 Jacob Bogers jkfbogers@gmail.com.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.