@eryx/path Module

High-level lexical path handling for Unix and NT/Windows grammars.

@eryx/path is the place to parse, inspect, and manipulate filesystem paths without touching the filesystem. It keeps path handling lexical: no implicit filesystem resolution, symlink expansion, or canonicalization. Use @eryx/fs for I/O and filesystem queries.

For most code, the common workflow is simple:

  1. Construct a path with new, newNt, or newUnix
  2. Use Path.join, Path.parent, Path.name, Path.stem, or Path.extension
  3. Pass the resulting Path directly into filesystem APIs, since they generally accept PathLike (Path | string)
  4. Use tostring(path) when you explicitly need the rendered string form

Most of the more specialized methods exist for Windows edge cases: UNC shares, verbatim paths, device namespaces, reserved DOS names, and other situations where a plain string is too lossy.

local fs = require("@eryx/fs")
local os = require("@eryx/os")
local path = require("@eryx/path")

local root = path.new(os.cwd())
local configFile = root:join("config"):join("app.json")

print(configFile:name())      -- "app.json"
print(configFile:stem())      -- "app"
print(configFile:extension()) -- "json"
print(configFile:parent())    -- Path(".../config")

if fs.exists(configFile) then
	local file = fs.open(configFile, "r")
	print(file:read())
	file:close()
end

If you only need everyday path manipulation, these methods are usually enough:

The top-level helpers are convenience wrappers around the Path object API. They are especially useful when you want familiar fs.path.*-style ergonomics while still working with parsed Path values.

If you only need the instance-style API, these methods are usually enough:

Warning

path.new(...) uses the host platform grammar. For deterministic parsing across platforms, prefer path.newNt(...) or path.newUnix(...).

Summary

Classes

_platform: Platform
_prefix: Prefix
_rooted: boolean
_components: { string }
_raw: string
_hadTrailingSeparator: boolean
Path:prefix()Prefix

Functions

path.new(input: PathLike)Path
path.join(base: PathLike, ...: PathLike)Path
path.isPath(value: any)boolean

API Reference

Classes

Path

Implements: PathData

Properties

_platform: Platform
_prefix: Prefix
_rooted: boolean
_components: { string }
_raw: string
_hadTrailingSeparator: boolean

Path:platform

Returns the grammar this path was parsed with.

Path:platform()Platform

Returns

Path grammar platform.

Path:prefix

Returns the parsed NT prefix, if any.

Unix paths always return nil.

Path:prefix()Prefix

Returns

Prefix

Prefix descriptor for NT/Windows paths.

Path:components

Returns the lexical path components excluding any prefix/root marker.

Path:components(){ string }

Returns

{ string }

Parsed path components.

Path:raw

Returns the original string passed to the parser.

This is primarily useful for round-tripping and diagnostics.

Path:raw()string

Returns

Original input string.

Path:hasPrefix

Returns whether the path has an explicit NT prefix such as a drive, UNC share, verbatim prefix, or device namespace.

Path:hasPrefix()boolean

Returns

true when a prefix is present.

Path:hasRoot

Returns whether the path is rooted.

On Windows this includes drive-rooted and rooted-without-prefix forms, but does not by itself imply the path is fully absolute.

Path:hasRoot()boolean

Returns

true when the path is rooted.

Path:isAbsolute

Returns whether the path is absolute in the current grammar.

On Windows this distinguishes C:\foo from drive-relative C:foo and rooted-relative \foo.

Path:isAbsolute()boolean

Returns

true when the path is absolute.

Path:isRelative

Returns whether the path is not absolute.

Path:isRelative()boolean

Returns

true when the path is relative.

Path:isUnc

Returns whether the path targets a UNC share.

This includes both ordinary UNC paths and verbatim UNC paths.

Path:isUnc()boolean

Returns

true when the path is UNC-like.

Path:isVerbatim

Returns whether the path uses a verbatim \\?\... namespace.

Path:isVerbatim()boolean

Returns

true when the path is verbatim.

Path:isDevice

Returns whether the path uses the \\.\... device namespace.

Path:isDevice()boolean

Returns

true when the path is a device path.

Path:isDriveRelative

Returns whether the path is Windows drive-relative, such as C:foo.

Path:isDriveRelative()boolean

Returns

true when the path is drive-relative.

Path:isRootedRelative

Returns whether the path is Windows rooted-relative, such as \foo.

Path:isRootedRelative()boolean

Returns

true when the path is rooted-relative.

Path:hasTrailingSeparator

Returns whether the original input ended with a separator.

Path:hasTrailingSeparator()boolean

Returns

true when a trailing separator was preserved.

Path:isReservedName

Returns whether the final component is a reserved DOS device name.

This is a query only; reserved names remain representable and are not parse failures.

Path:isReservedName()boolean

Returns

true when the final component is reserved on Windows.

Path:hasProblematicTrailingChars

Returns whether the final component ends in a trailing dot or space.

These names often require verbatim handling on Windows.

Path:hasProblematicTrailingChars()boolean

Returns

true when the final component has problematic trailing characters.

Path:needsVerbatim

Returns whether this path likely benefits from a verbatim Windows form.

The current heuristic checks for problematic trailing characters and long rendered paths.

Path:needsVerbatim()boolean

Returns

true when a verbatim form is recommended.

Path:name

Returns the final path component, if any.

Path:name()string?

Returns

Final component, or nil for roots/share roots.

Path:stem

Returns the final component without its last extension.

Path:stem()string?

Returns

Stem of the final component, or nil when absent.

Path:extension

Returns the last extension of the final component without a leading dot.

Path:extension()string?

Returns

Extension text, or nil when absent.

Path:parent

Returns the lexical parent path, or nil for roots/share roots.

Path:parent()Path?

Returns

Parent path when one exists.

Path:withName

Returns a copy of the path with the final component replaced.

Path:withName(name: string)Path

Parameters

name: string

Replacement final component. Must be a single component.

Returns

New path with the updated name.

Path:withExtension

Returns a copy of the path with the final component's extension changed.

Leading dots in ext are ignored. Pass an empty string to remove the extension entirely.

Path:withExtension(ext: string)Path

Parameters

ext: string

New extension text.

Returns

New path with the updated extension.

Path:joinComponent

Appends a single normal path component.

This rejects separators and the special "." / ".." components.

Path:joinComponent(name: string)Path

Parameters

name: string

Path component to append.

Returns

New path with the appended component.

Path:join

Joins another path onto this one using lexical platform rules.

On Unix, rooted RHS values replace the whole path. On Windows, fully qualified RHS values replace the whole path, while rooted-without-prefix RHS values preserve the current volume where appropriate.

Path:join(rhs: PathLike)Path

Parameters

PathLike value to join.

Returns

Joined path.

Path:normalizeDots

Performs lexical . / .. cleanup.

On verbatim Windows paths this is intentionally a no-op by default.

Path:normalizeDots()Path

Returns

Normalized path.

Path:normalizeDotsUnsafe

Performs lexical . / .. cleanup even for verbatim paths.

Use this only when you explicitly want that behavior.

Path:normalizeDotsUnsafe()Path

Returns

Normalized path.

Path:normalizeSeparators

Returns a copy of the path in normalized separator form.

For verbatim Windows paths this is conservative and currently returns the path unchanged.

Path:normalizeSeparators()Path

Returns

Path with normalized separators.

Path:relativeTo

Computes a lexical relative path from base to this path.

This is purely syntactic and refuses paths with mismatched platforms, volumes, prefixes, or rootedness.

Path:relativeTo(base: PathLike)Path?

Parameters

base: PathLike

Base path to relativize against.

Returns

Relative path, or nil when no lexical relative form exists.

Path:toNativeString

Returns the native string form used when crossing into C++ path-taking APIs.

Path:toNativeString()string

Returns

Native path string.

Path:toDisplayString

Returns a display-oriented string form.

For verbatim disk/UNC paths this strips the verbatim marker while preserving the lexical structure.

Path:toDisplayString()string

Returns

Display-friendly path string.

Path:toVerbatimString

Returns a verbatim Windows string form when possible.

Unix paths and already-verbatim paths are returned unchanged.

Path:toVerbatimString()string

Returns

Verbatim or unchanged path string.

Functions

path.parseNative

Parses a string using the host platform grammar.

Prefer newNt or newUnix when deterministic grammar selection matters.

path.parseNative(input: string)Path

Parameters

input: string

Path string to parse.

Returns

Parsed path object.

path.parseNt

Parses a string using Windows/NT path rules.

path.parseNt(input: string)Path

Parameters

input: string

Path string to parse.

Returns

Parsed NT path object.

path.parseUnix

Parses a string using Unix path rules.

path.parseUnix(input: string)Path

Parameters

input: string

Path string to parse.

Returns

Parsed Unix path object.

path.new

Constructs a path using the host platform grammar.

If input is already a Path, it is returned unchanged.

Warning

This constructor is host-native and may be unpredictable for cross-platform-sensitive code. Prefer newNt or newUnix for deterministic parsing.

path.new(input: PathLike)Path

Parameters

input: PathLike

Path string or existing Path.

Returns

Parsed path object.

path.newNt

Constructs a path using Windows/NT path rules.

If input is already an NT Path, it is returned unchanged.

path.newNt(input: PathLike)Path

Parameters

input: PathLike

Path string or existing Path.

Returns

Parsed NT path object.

path.newUnix

Constructs a path using Unix path rules.

If input is already a Unix Path, it is returned unchanged.

path.newUnix(input: PathLike)Path

Parameters

input: PathLike

Path string or existing Path.

Returns

Parsed Unix path object.

path.join

Joins path segments using the lexical rules of the first argument.

This is a convenience wrapper over repeated Path.join calls and accepts a PathLike as its first argument.

path.join(base: PathLike, ...: PathLike)Path

Parameters

base: PathLike

Base path.

Additional path segments to join.

Returns

Joined path.

path.dirname

Returns the lexical parent directory of a path.

This is a convenience wrapper over Path.parent.

path.dirname(input: PathLike)Path?

Parameters

input: PathLike

Path to inspect.

Returns

Parent path, or nil for roots/share roots.

path.basename

Returns the final component of a path.

This is a convenience wrapper over Path.name.

path.basename(input: PathLike)string?

Parameters

input: PathLike

Path to inspect.

Returns

Final component, or nil when absent.

path.stem

Returns the final component without its last extension.

This is a convenience wrapper over Path.stem.

path.stem(input: PathLike)string?

Parameters

input: PathLike

Path to inspect.

Returns

Stem text, or nil when absent.

path.extension

Returns the last extension of the final component without a leading dot.

This is a convenience wrapper over Path.extension.

path.extension(input: PathLike)string?

Parameters

input: PathLike

Path to inspect.

Returns

Extension text, or nil when absent.

path.canonicalize

Resolves a path to an absolute canonical form via the filesystem.

Unlike most of @eryx/path, this helper is not purely lexical. It bridges into a native filesystem helper and returns the canonicalized result as a Path.

path.canonicalize(input: PathLike)Path

Parameters

input: PathLike

Path to canonicalize.

Returns

Canonical absolute path.

path.isPath

Returns whether a value is a parsed Path object.

path.isPath(value: any)boolean

Parameters

value: any

Value to test.

Returns

true when the value is a Path.

Types

NtPrefix

Windows/NT path prefix descriptor.

These variants distinguish ordinary drive paths, UNC shares, verbatim paths, and device namespace paths without collapsing them into a single string form.

type NtPrefix = { kind: "disk", letter: string } | { kind: "unc", server: string, share: string } | { kind: "verbatim_disk", letter: string } | { kind: "verbatim_unc", server: string, share: string } | { kind: "device", name: string } | { kind: "verbatim", head: string }

PathLike

A filesystem path accepted by high-level and native path-taking APIs.

This may be either a raw string or a parsed Path object.