dt

package module
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 23, 2025 License: MIT Imports: 20 Imported by: 21

README

Domain Types for Go (dt)

Purpose

dt provides a stable, dependency-free foundation of common domain types for Go—types that are “good enough” for everyone to use, even if not perfect for every use-case.

Software ecosystems thrive when developers can build on shared assumptions instead of constantly reinventing them. dt aims to be that shared foundation: a stake in the ground for how common types like file paths, identifiers, and URLs that can be used in your packages with the knowledge that other packages can have access to those same types.

We’re not trying to design the ideal type for every situation. We’re trying to make it easy to agree on something usable so that code written by different teams and libraries can interoperate seamlessly.

When you write Go code using the standard library, you don’t have to ask whether string or os.FileInfo will be available to the next developer; they simply are. The goal of dt is to bring that same confidence and low-friction usability to domain types that the standard library never standardized.


Status

This is pre-alpha and in development, thus subject to change—though I'm working toward v1.0 with confidence that the architecture is approaching stability. As of December 2025, I'm actively developing and using it in current projects.

If you find value in this project and want to use it, please open a discussion to let me know. If you discover any issues, please open an issue or submit a pull request.


Stability & Compatibility Policy

dt uses explicit stability levels for exported symbols:

  • Stable: no breaking changes to symbol identity or documented behavior
  • Provisional: likely safe for production, but may still change as naming/shape matures
  • Experimental: may change or disappear without notice
  • Deprecated: scheduled for removal with a published removal floor
  • Obsolete: retained for compatibility but should not be used
  • Internal: exported for technical reasons but not part of the public API

Alignment note: OpenTelemetry provides useful prior art for maturity ladders and deprecation floors; this repo borrows vocabulary and minimum floors, but retains symbol-level enforcement goals that OTel does not target for Go API identifiers.

Deprecation Policy

For Deprecated symbols:

  • Minimum removal floor: 2 minor releases or 6 months, whichever is later
  • Required metadata: RemoveAfter and Replacement
  • We meet OTel's minimum and may exceed it; the symbol-level contract is authoritative

How to Read Contract Blocks

Contract blocks are machine-readable doc comments attached to exported identifiers.

// Filepath represents a filesystem path including a filename.
//
// Contract:
// - Stability: Stable
// - Since: v0.6.0
// - Note: Methods are stable and will not change without a major version.
type Filepath string

Deprecated items also include:

// - Deprecated: v0.8.0
// - RemoveAfter: v1.0.0 or 2026-01-01
// - Replacement: dt.NewFilepath

Tooling / CI (planned)

Planned tooling makes contracts enforceable:

  • Extract Contract: blocks into a generated JSON index
  • Validate that Deprecated items include RemoveAfter and Replacement
  • Use golang.org/x/exp/apidiff to detect breaking changes
  • Fail CI when Stable contracts break without a major version bump

Rationale

Many Go developers recognize that custom domain types can improve correctness and readability. Yet few actually use them, because in today’s ecosystem doing so requires too much effort.

The barrier is friction. Even simple types like Filename or DirPath often demand re-implementing helper methods, sacrificing interoperability with third-party libraries, and working around the standard library’s limited type flexibility.

dt envisions a future where that friction is greatly reduced.


Why dt Exists

"When different packages from different authors both use dt.Filepath or dt.DirPath, they can exchange values directly. No glue code, no type conversions, and greatly reduced risk of mismatched assumptions."
— The dt team

Today, developers who use custom types end up isolated. A package defining its own FilePath or DirPath cannot interoperate cleanly with others that do the same. Every ecosystem needs a shared vocabulary.

For Go, we hope that dt can be that vocabulary.


The Problem We’re Solving

Using domain types in Go shouldn’t feel like swimming upstream.

Because the Go standard library works almost exclusively with built-in types (string, int, etc.), developers are discouraged from introducing semantic wrappers—even when they make code safer and more expressive. dt solves this by doing the hard part once, in one place, and promising to keep it stable.

We want to make it easy and obvious to choose dt.Filename instead of string, and to know that everyone else is doing the same.


Our Goal

A community-driven, well-designed set of types that:

  • 🧱 Provide semantic clarity for common domains (files, identifiers, URLs, etc.).
  • ⚙️ Work seamlessly with the Go standard library and third-party packages.
  • 🔄 Enable interoperability across projects and teams.
  • 🧭 Are stable and intuitive, with minimal learning curve.
  • 🌍 Encourage a shared ecosystem vocabulary.

Our reasonable goal is broad adoption: if enough developers and library authors agree to depend on dt, interoperability naturally follows.

Our ultimate goalsaid with a wink — is to see the Go team adopt something like dt officially, perhaps as golang.org/x/dt. Whether or not that ever happens, the mission remains the same: to make domain types first-class citizens in Go.


The Gofmt Analogy

As Rob Pike noted:

"Gofmt's style is no one's favorite, yet gofmt is everyone's favorite."

We believe the same principle could (should?) apply to this Domain Types package:

"Types in Domain Types are no one's favorite, yet the Types in Domain Types are everyone's favorite."

Just as gofmt succeeds by being good enough rather than perfect, dt succeeds by establishing a shared vocabulary that everyone can build on. It's not about designing the ideal type for every situation—it's about making it easy to agree on something usable, so developers and libraries can interoperate seamlessly without constant friction.


Our Promise

  • 🧩 Simplicity: Each type does one thing and does it well.
  • 🛠️ Minimal Logic: No complex behavior—just useful helpers like ReadFile() or EnsureExists() that feel native to Go.
  • 🧭 Stability: After v1.0.0, no breaking changes without a major bump.
  • 🕰️ Longevity: Designed to remain relevant for many years without redesign.
  • 🧑‍🤝‍🧑 Interoperability: Always safe to use in your own packages and libraries.

Design Choice: Methods Over Package Functions

If you're coming from the Go standard library, you might notice that dt frequently uses methods on types rather than package-level functions:

// Standard library typically uses package functions
var fp string
...
content, err := os.ReadFile(fp)
dir := filepath.Dir(dp)

// dt typically uses methods
var fp dt.Filepath
...
content, err := fp.ReadFile()
dir := fp.Dir()

This is not a stylistic preference. It's a pragmatic response to a technical limitation.

Go's generics system (as of Go 1.25) simply cannot express the type relationships needed to make package functions work ergonomically with domain types. Defaulting to package functions in dt would force constant type casting, defeating the impetus behind dt, to provide greater type safety that string and other built-in types provide without having to constantly cast values from one derived type to another type derived from the same base type:

// A package function approach would require verbose casting
var myPath dt.Filepath
var myDir dt.DirPath
...
myDir = dt.DirPath(filepath.Dir(string(myPath))

// Whereas a method approach is clean and type-safe
var myPath dt.Filepath
var myDir dt.DirPath
...
myDir = myPath.Dir()

The method-based approach provides:

  • Type-casting rarely required – operations are attached to the type for better ergonomics
  • Better discoverability – IDE autocompletes will shows all available operations
  • Cleaner composition – Chaining for those who prefer it, e.g.: dir.Join(file).ReadFile()
  • And best of all: Type safety – The Go compiler prevents invalid type compositions

For a detailed technical explanation of this decision, see ADR 2025-02-11: Methods Over Package Functions.


Type Classification

dt provides two categories of types:

Core Types

Domain types that model real-world concepts and are intended to be used as replacements for built-in types like string. These represent semantic entities: file paths, identifiers, URLs, versions, and the like.

Examples: Filename, Filepath, DirPath, URL, Identifier, Version

Supplemental Types

Types that provide essential functionality for core types—either as containers or enumerations. These are used alongside core types to enable safe operations and type-safe classification.

Examples: DirEntry (container), EntryStatus (enumeration)


Type Hierarchy

The following diagram shows how dt types relate to one another, from broad to narrow:

Types
├── Supplemental Types
│   ├── DirEntry (used during directory walking)
│   └── EntryStatus (enumeration: FileEntry, DirEntry, SymlinkEntry, etc.)
└── Core Types (all extend string)
    ├── Identifier (validated identifiers)
    ├── TimeFormat (time layout strings)
    ├── Version (software version strings)
    ├── EntryPath (generic file or directory path)
    │   ├── DirPath (directory path)
    │   │   ├── TildeDirPath (tilde-prefixed directory path)
    │   │   ├── VolumeName (Windows volume identifier)
    │   │   └── PathSegments
    │   │       └── PathSegment (single path component)
    │   └── Filepath (file path with filename)
    │       ├── RelFilepath (relative file path with traversal protection)
    │       │   └── Filename (filename without path)
    │       │       └── FileExt (file extension with leading period)
    │       └── Filename (filename without path)
    │           └── FileExt (file extension with leading period)
    ├── RelPath (generic relative file or directory path)
    │   ├── PathSegments
    │   │   └── PathSegment (single path component)
    │   └── RelFilepath (relative file path with traversal protection)
    │       └── Filename (filename without path)
    │           └── FileExt (file extension with leading period)
    ├── InternetDomain (internet domain names)
    └── URL (syntactically valid URLs)
        ├── URLSegments (URL path components)
        │   └── URLSegment (single URL path component)
        └── Filename (when used in URL contexts)
            └── FileExt

Parse Functions

Many types in dt have associated Parse<Type>() functions:

filename, err := dt.ParseFilename("config.json")
url, err := dt.ParseURL("https://example.com")
version, err := dt.ParseVersion("1.2.3")

Current Status: These functions are currently lightweight casting functions. Over time, they will evolve to include robust validation similar to url.Parse() from the standard library.

Future Intent: As validation is implemented progressively, the type hierarchy understanding will evolve to reflect validated constraints. This design ensures dt can add validation without breaking existing code.


File Type Semantics

Throughout the dt API, the term "file" specifically means regular file, as determined by fs.FileMode.IsRegular(). This aligns with Go standard library conventions.

What is a "Regular File"?

A regular file is a normal data file—the most common file system entry type. It excludes:

  • Directories
  • Symbolic links
  • Named pipes (FIFOs)
  • Unix sockets
  • Device files (block or character)
  • Other irregular entries
API Implications

Methods and functions with "File" in their name operate on regular files only:

  • IsFile() — Returns true only for regular files
  • WalkFiles() — Yields only regular files
  • Filename() — Available for regular files

To process all entry types including symlinks and special files, use:

  • Walk() — Yields all entry types
  • Status() — Classify entry type
  • Pattern matching on EntryStatus values
Example: Handling Different Entry Types
func processAllEntries(root dt.DirPath) (err error) {
    for entry := range root.Walk() {
        var status dt.EntryStatus

        status = entry.Status()

        switch status {
        case dt.IsFileEntry:
            // Regular file
            fmt.Println("File:", entry.Filename())

        case dt.IsDirEntry:
            // Directory
            fmt.Println("Dir:", entry.DirPath())

        case dt.IsSymlinkEntry:
            // Symbolic link
            var target dt.EntryPath
            var path dt.EntryPath

            path = entry.EntryPath()
            target, err = path.Readlink()
            if err != nil {
                goto end
            }
            fmt.Println("Symlink:", path, "->", target)

        case dt.IsSocketEntry, dt.IsPipeEntry, dt.IsDeviceEntry:
            // Special file types
            fmt.Println("Special:", entry.EntryPath())

        default:
            // Unknown or error
            fmt.Println("Other:", entry.EntryPath())
        }
    }

end:
    return err
}

This distinction ensures type safety and predictable behavior across the API.


Types and APIs

Filesystem Path Types

Filesystem paths are the core focus of dt. They represent locations on the filesystem and provide type-safe operations for reading, writing, and navigation.

DirPath

Represents a filesystem directory path (absolute or relative).

Key Methods:

  • EnsureExists() — Create directory and parents if needed; error if path exists as file
  • ReadDir() — List directory contents
  • Walk() — Iterate through directory tree with SkipDir() support
  • WalkFiles() — Iterate through regular files only
  • WalkDirs() — Iterate through directories only
  • Join(...any) — Join path components
  • Dir() — Parent directory
  • Base() — Directory name as PathSegment
  • Clean() — Normalize path
  • Stat() — Get file info (follows symlinks)
  • Lstat() — Get file info without following symlinks
  • Exists() — Check existence
  • DirFS() — Convert to fs.FS

Comprehensive Example:

func processDirPath() (err error) {
    var dir dt.DirPath
    var subDir dt.DirPath
    var configFile dt.Filepath

    dir = dt.DirPath("/home/user/projects")
    err = dir.EnsureExists()
    if err != nil {
        goto end
    }

    // Walk all regular files recursively
    for entry := range dir.WalkFiles() {
        fmt.Println("File:", entry.Filename())
    }

    // Create and navigate subdirectory
    subDir = dir.Join("src", "main")
    err = subDir.EnsureExists()
    if err != nil {
        goto end
    }

    // Work with files in subdirectory
    configFile = dt.FilepathJoin(subDir, "config.json")
    err = configFile.WriteFile([]byte("{}"), 0o644)
    if err != nil {
        goto end
    }

end:
    return err
}
TildeDirPath

Directory path with tilde (~) prefix for user home directory expansion.

Key Methods:

  • Expand() — Expand tilde to full path

Package Function:

  • ParseTildeDirPath(s string) — Parse string as tilde directory path

Example:

func processHomePath() (dir dt.DirPath, err error) {
    var tildePath dt.TildeDirPath

    tildePath, err = dt.ParseTildeDirPath("~/projects/go-dt")
    if err != nil {
        goto end
    }

    dir, err = tildePath.Expand()
    if err != nil {
        goto end
    }

    fmt.Println("Expanded path:", dir)

end:
    return dir, err
}

Note: Expand() is not strict about tilde path validity. It will expand any path, including non-tilde paths like ".", by resolving them relative to the user's home directory. It only returns an error if the underlying os.UserHomeDir() call fails.

Filepath

Represents a complete file path including filename and extension.

Key Methods:

  • ReadFile() — Read file contents
  • WriteFile(data, mode) — Write file
  • Create() — Create file
  • OpenFile(flag, mode) — Open with flags
  • Dir() — Parent directory as DirPath
  • Base() — Filename as Filename
  • Ext() — File extension as FileExt
  • Stat(), Lstat() — File info
  • Exists() — Check existence
  • CopyTo(dest, opts) — Copy file to destination with optional settings
  • CopyToDir(dest, opts) — Copy file to destination directory
  • Remove() — Delete file

Comprehensive Example:

func processFile() (data []byte, err error) {
    var file dt.Filepath
    var dir dt.DirPath

    file = dt.Filepath("/home/user/config.json")

    // Check and read file
    if ok, statErr := file.Exists(); !ok {
        err = statErr
        goto end
    }

    data, err = file.ReadFile()
    if err != nil {
        goto end
    }

    // Get parent directory
    dir = file.Dir()
    fmt.Println("Config location:", dir)

    // Copy to backup
    backup := dt.FilepathJoin(dir, "config.json.bak")
    err = file.CopyTo(backup, nil)
    if err != nil {
        goto end
    }

end:
    return data, err
}
RelFilepath

Represents a relative file path with protections against directory traversal attacks. Validates that the path does not attempt to escape the intended directory using ../ sequences.

Key Methods:

  • Dir() — Parent directory
  • Base() — Filename
  • ValidPath() — Check path validity
  • Stat(fileSys ...fs.FS) — Get file info
  • ReadFile(fileSys ...fs.FS) — Read file contents
  • WriteFile(data, mode) — Write file
  • Rel(baseDir) — Get relative path
  • Exists() — Check existence
  • Status(flags) — Get entry status

Note: RelFilepath currently has fewer methods than Filepath. This is not a fundamental design constraint—additional methods will be added as use cases arise. The limited method set reflects practical usage patterns rather than architectural limitations.

Example:

func processUserFile(userPath string) (data []byte, err error) {
    var relPath dt.RelFilepath
    var valid bool

    relPath = dt.RelFilepath(userPath)
    valid = relPath.ValidPath()
    if !valid {
        err = errors.New("invalid relative path")
        goto end
    }

    data, err = relPath.ReadFile()
    if err != nil {
        goto end
    }

end:
    return data, err
}
RelPath

Generic relative path that can represent either a file or directory. Similar to EntryPath but constrained to relative paths.

Key Methods:

  • Dir() — Parent directory
  • Base() — Base name as PathSegment
  • Stat(fileSys ...fs.FS) — Get file info
  • Lstat() — Get file info without following symlinks
  • Status(flags) — Get entry status
  • Readlink() — Resolve symlink target
  • VolumeName() — Get volume name
  • Abs() — Convert to absolute path
  • Join(elems ...any) — Join path components
  • HasSuffix(suffix), Contains(substr) — String operations

Example:

func processRelativePath(rel dt.RelPath) (err error) {
    var abs dt.RelPath
    var status dt.EntryStatus

    abs, err = rel.Abs()
    if err != nil {
        goto end
    }

    status, err = abs.Status()
    if err != nil {
        goto end
    }

    fmt.Printf("Path: %s, Type: %s\n", abs, status)

end:
    return err
}
EntryPath

Generic filesystem entry path that can represent either a file or directory. Use when the type is unknown until runtime.

Key Methods:

  • Dir() — Parent directory
  • Base() — Base name as PathSegment
  • Stat(fileSys ...fs.FS) — Get file info
  • Lstat() — Get file info without following symlinks
  • Status(flags ...EntryStatusFlags) — Get entry type classification
  • Readlink() — Resolve symlink target
  • VolumeName() — Get volume name (Windows)
  • Abs() — Get absolute path
  • Join(elems ...any) — Join path components
  • HasSuffix(suffix), Contains(substr) — String operations
  • EnsureTrailSep() — Ensure trailing separator
  • HasDotDotPrefix() — Check for .. prefix

Type Checking Pattern:

func processEntry(ep dt.EntryPath) (err error) {
    var status dt.EntryStatus

    status, err = ep.Status()
    if err != nil {
        goto end
    }

    switch status {
    case dt.IsFileEntry:
        fp := dt.Filepath(ep)
        // Handle regular file
    case dt.IsDirEntry:
        dp := dt.DirPath(ep)
        // Handle directory
    case dt.IsSymlinkEntry:
        var target dt.EntryPath

        target, err = ep.Readlink()
        if err != nil {
            goto end
        }
        // Handle symlink
    case dt.IsSocketEntry, dt.IsPipeEntry, dt.IsDeviceEntry:
        // Handle or skip special types
    }

end:
    return err
}

Note: EntryPath does not have IsFile() or IsDir() methods. Use Status() for type classification and cast to the appropriate type.

Filename

Filename without any path component.

Key Methods:

  • Ext() — Extension as FileExt
  • String() — Get filename as string

Example:

fn := dt.Filename("document.txt")
ext := fn.Ext()        // FileExt(".txt")
name := fn.String()    // "document.txt"
FileExt

File extension including the leading period.

Type: FileExt is a bare string type with no public methods.

Usage:

ext := dt.FileExt(".txt")
name := string(ext)  // Convert to string when needed

Note: FileExt currently has no methods. Extension validation and manipulation can be done through standard string operations after casting.

Path Components and Segments

Working with components of filesystem paths.

PathSegments

Represents a filesystem path as a string with segment operations.

Key Methods:

  • Split() — Split into []PathSegment using OS separator
  • Segment(index) — Get segment at index
  • Slice(start, end) — Get segment slice (supports end == -1 for "to last")
  • SliceScalar(start, end) — Get joined substring of segments without intermediate allocations
  • LastIndex(sep) — Find last occurrence of separator

Example:

path := dt.PathSegments("home/user/projects/file.go")
segments := path.Split()                // []PathSegment{"home", "user", ...}
segment := path.Segment(1)              // "user"
slice := path.Slice(0, 3)               // first 3 segments
scalar := path.SliceScalar(0, 3)        // "home/user/projects"
PathSegment

A single filesystem path component.

Key Methods:

  • HasPrefix(prefix), HasSuffix(suffix) — String prefix/suffix checks
  • TrimPrefix(prefix), TrimSuffix(suffix) — Remove prefix/suffix
  • Contains(substr) — Check substring presence
URL Types

Working with URLs and URL components.

URL

Represents a syntactically valid Uniform Resource Locator.

Key Methods:

  • Parse() — Parse into *url.URL for detailed access
  • GET(client) — Perform HTTP GET request
  • HTTPGet(client) — Perform HTTP GET request (alias)

Comprehensive Example:

func fetchData(endpoint string) (body []byte, err error) {
    var apiURL dt.URL
    var resp *http.Response

    apiURL, err = dt.ParseURL(endpoint)
    if err != nil {
        goto end
    }

    resp, err = apiURL.GET(http.DefaultClient)
    if err != nil {
        goto end
    }
    defer resp.Body.Close()

    body, err = io.ReadAll(resp.Body)
    if err != nil {
        goto end
    }

end:
    return body, err
}
URLSegments

Represents URL path segments (parts separated by /).

Key Methods:

  • Split() — Split into []URLSegment
  • Segment(index) — Get segment at index
  • Slice(start, end) — Get segment slice
  • SliceScalar(start, end, sep) — Get joined scalar with custom separator
  • LastIndex(sep) — Find last occurrence of separator
  • Base() — Last segment as URLSegment

Example:

segments := dt.URLSegments("api/v1/users/123")
all := segments.Split()                     // []URLSegment{"api", "v1", "users", "123"}
middle := segments.Slice(1, 3)              // []URLSegment{"v1", "users"}
scalar := segments.SliceScalar(1, 3, "/")   // "v1/users"
last := segments.Base()                     // "123"
URLSegment

A single URL path component, semantically different from a PathSegment.

Helper Types
Identifier

A string type representing validated identifiers suitable for Git references, semantic version components, and similar uses.

Example:

ref := dt.Identifier("main")
tag := dt.Identifier("v1.2.3")
Version

Software version string following semantic versioning conventions.

Key Methods:

  • Major(), Minor(), Patch() — Extract version components
  • Valid() — Check if version is valid
InternetDomain

Internet domain name (e.g., example.com).

Key Methods:

  • Valid() — Validate domain format
  • TLD() — Extract top-level domain
  • String() — Get as string
TimeFormat

Time layout string for use with time.Parse() and time.Format().

VolumeName

Mounted volume name, primarily for Windows support (e.g., C:).

Directory Entry and Status
DirEntry

Represents a filesystem entry encountered during directory walking.

Key Methods:

  • Name() — Entry name as PathSegment
  • Filename() — Filename as Filename (if file)
  • DirPath() — Full path as DirPath
  • Filepath() — Full path as Filepath (if file)
  • Status() — Entry type as EntryStatus
  • IsFile(), IsDir(), IsSymlink() — Type checks
  • Info() — Get underlying fs.FileInfo
EntryStatus

Enumeration classifying filesystem entries:

  • FileEntry — Regular file
  • DirEntry — Directory
  • SymlinkEntry — Symbolic link
  • UnknownEntry — Other or unknown type

Generic Segment Operations

These functions work with any string type and separator, providing zero-cost abstractions for delimited string manipulation.

SplitSegments
func SplitSegments[S ~string](s, sep string) []S

Splits a string by separator into typed segments. Pre-counts separators for optimal memory allocation.

Example:

func example() {
    segments := dt.SplitSegments[dt.PathSegment]("home/user/projects", "/")
    // segments = []PathSegment{"home", "user", "projects"}
}
IndexSegments
func IndexSegments[S ~string](s, sep string, index int) S

Returns the segment at the given index. Returns empty string if index is out of bounds or negative.

Example:

func example() {
    segment := dt.IndexSegments[dt.PathSegment]("home/user/projects", "/", 1)
    // segment = "user"
}
SliceSegments
func SliceSegments[S ~string](s, sep string, start, end int) []S

Returns a slice of segments from start (inclusive) to end (exclusive). Supports end == -1 to mean "to the last segment". Returns empty slice if indices are invalid.

Example:

func example() {
    segments := dt.SliceSegments[dt.PathSegment]("home/user/projects/file.go", "/", 1, 3)
    // segments = []PathSegment{"user", "projects"}
}
SliceSegmentsScalar
func SliceSegmentsScalar[S ~string](s, sep string, start, end int) S

Like SliceSegments, but returns a joined scalar string instead of a slice. Zero heap allocations — uses single-pass byte position tracking, ideal for extracting contiguous segment ranges.

Performance Note: This function is optimized for memory efficiency with exactly one pass through the input string without creating intermediate data structures.

Example:

func example() {
    result := dt.SliceSegmentsScalar[dt.PathSegment]("home/user/projects/file.go", "/", 1, 3)
    // result = "user/projects" (no intermediate allocations)
}
JoinSegments
func JoinSegments[S ~string](ss []S, sep string) S

Joins a slice of segments with a separator. Pre-calculates required capacity for minimal allocations.

Example:

func example() {
    segments := []dt.PathSegment{"home", "user", "projects"}
    result := dt.JoinSegments(segments, "/")
    // result = "home/user/projects"
}

Type-Safe Join Functions

dt provides generic join functions for safely combining path and URL components with type preservation. These functions use generics to accept any string-like types.

Filesystem Path Join Functions
// Generic join functions for any string-like types
func DirPathJoin[T1, T2 ~string](a T1, b T2) DirPath
func DirPathJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) DirPath
func DirPathJoin4[T1, T2, T3, T4 ~string](a T1, b T2, c T3, d T4) DirPath
func DirPathJoin5[T1, T2, T3, T4, T5 ~string](a T1, b T2, c T3, d T4, e T5) DirPath

func FilepathJoin[T1, T2 ~string](a T1, b T2) Filepath
func FilepathJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) Filepath
func FilepathJoin4[T1, T2, T3, T4 ~string](a T1, b T2, c T3, d T4) Filepath
func FilepathJoin5[T1, T2, T3, T4, T5 ~string](a T1, b T2, c T3, d T4, e T5) Filepath

func RelFilepathJoin[T1, T2 ~string](a T1, b T2) RelFilepath
func RelFilepathJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) RelFilepath
func RelFilepathJoin4[T1, T2, T3, T4 ~string](a T1, b T2, c T3, d T4) RelFilepath
func RelFilepathJoin5[T1, T2, T3, T4, T5 ~string](a T1, b T2, c T3, d T4, e T5) RelFilepath

func EntryPathJoin[T1, T2 ~string](a T1, b T2) EntryPath
func EntryPathJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) EntryPath
func EntryPathJoin4[T1, T2, T3, T4 ~string](a T1, b T2, c T3, d T4) EntryPath
func EntryPathJoin5[T1, T2, T3, T4, T5 ~string](a T1, b T2, c T3, d T4, e T5) EntryPath
Path Segment Join Functions
func PathSegmentsJoin[T1, T2 ~string](a T1, b T2) PathSegments
func PathSegmentsJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) PathSegments
URL Join Functions
func URLJoin[T1, T2 ~string](a T1, b T2) URL
func URLJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) URL
func URLJoin4[T1, T2, T3, T4 ~string](a T1, b T2, c T3, d T4) URL
func URLJoin5[T1, T2, T3, T4, T5 ~string](a T1, b T2, c T3, d T4, e T5) URL

func URLSegmentsJoin[T1, T2 ~string](a T1, b T2) URLSegments
func URLSegmentsJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) URLSegments

Example:

func buildPaths() {
    baseDir := dt.DirPath("/home/user")

    // Join accepts any string-like types
    subDir := dt.DirPathJoin(baseDir, "projects")
    configFile := dt.FilepathJoin(baseDir, "config.json")

    // Fixed-arity versions for multiple components
    logFile := dt.FilepathJoin3(baseDir, "logs", "app.log")
}

OS Wrapper Functions

dt wraps common os package functions with type safety.

Directory Operations
func MkdirAll(path dt.DirPath, perm os.FileMode) error
func MkdirTemp(dir dt.DirPath, pattern string) (dt.DirPath, error)
func RemoveAll(path dt.DirPath) error
File Operations
func CreateFile(path dt.Filepath) (*os.File, error)
func CreateTemp(dir dt.DirPath, pattern string) (*os.File, error)
func ReadFile(path dt.Filepath) ([]byte, error)
func WriteFile(path dt.Filepath, data []byte, perm os.FileMode) error
Working Directory and Home
func Getwd() (dt.DirPath, error)
func TempDir() dt.DirPath
func UserHomeDir() (dt.DirPath, error)
func UserConfigDir() (dt.DirPath, error)
func UserCacheDir() (dt.DirPath, error)
Filesystem Introspection
func DirFS(path dt.DirPath) fs.FS

Example:

func setupApplicationDirs() (err error) {
    var homeDir dt.DirPath
    var configDir dt.DirPath

    homeDir, err = dt.UserHomeDir()
    if err != nil {
        goto end
    }

    configDir = dt.DirPathJoin(homeDir, ".config", "myapp")
    err = dt.MkdirAll(configDir, 0o755)
    if err != nil {
        goto end
    }

    tempDir, err := dt.MkdirTemp(dt.TempDir(), "myapp-*")
    if err != nil {
        goto end
    }
    defer dt.RemoveAll(tempDir)

end:
    return err
}

Error Handling

dt uses the structured error system from the doterr package internally. We recommend you use doterr as well for consistent error handling throughout your applications.

Reference: See go-doterr for complete documentation on structured error metadata and chaining.


Utility Functions

File Status Checking
func CanWrite(path dt.Filepath) (bool, error)
func Stat(path dt.EntryPath) (os.FileInfo, error)
func StatFile(path dt.Filepath) (os.FileInfo, error)
func StatDir(path dt.DirPath) (os.FileInfo, error)
File Time Operations
func Chtimes(path dt.EntryPath, atime, mtime time.Time) error
func ChangeFileTimes(path dt.Filepath, atime, mtime time.Time) error
func ChangeDirTimes(path dt.DirPath, atime, mtime time.Time) error
Time Formatting Utilities
func ParseTimeDurationEx(duration string) (time.Duration, error)
Logging
func Logger() *slog.Logger
func SetLogger(logger *slog.Logger)
func EnsureLogger()
func LogOnError(err error)
func CloseOrLog(closer io.Closer)

Example:

func checkFileAccess(filePath dt.Filepath) (err error) {
    var info os.FileInfo
    var canWrite bool

    canWrite, err = dt.CanWrite(filePath)
    if err != nil {
        goto end
    }

    info, err = dt.StatFile(filePath)
    if err != nil {
        goto end
    }

    fmt.Printf("File: %s, Writable: %v, Size: %d\n",
        filePath, canWrite, info.Size())

end:
    return err
}

Companion Packages

dtx (Experimental Extensions)

Experimental types and utilities under evaluation for potential inclusion in the main dt package. Safe for production use with strong compatibility guarantees, though subject to evolution when necessary.

Key Features:

  • GetWorkingDir() — OS-aware working directory detection with hint support
  • IsZero(), IsNil(), IsNilable(), IsNilableKind() — Type introspection helpers
  • Must() — Panic on error helper for fail-fast patterns
  • Panicf() — Formatted panic function
  • AssertType() — Safe type assertion with panic fallback
  • TempTestDir(), SetTestEnv() — Testing and environment helpers
  • OS-specific path segment parsers (Windows, Darwin, Linux)
  • EntryStatusError() — Convert EntryStatus to error types

Package: go-dt/dtx

dtglob (Glob Patterns)

Pattern-based file operations with glob-style matching and bulk copy operations.

Key Features:

  • Glob — Type-safe glob pattern representation
  • GlobRule — Single file copy operation specification
  • GlobRules — Container for multiple rules with batch CopyTo() operation

Package: go-dt/dtglob (if available in your installation)

appinfo (Application Metadata)

Standard interface for describing application metadata across the ecosystem.

Key Features:

  • AppInfo interface — Contract for application metadata including name, version, config paths
  • New(Args) — Create concrete AppInfo implementations
  • Test helpers for verifying AppInfo implementations

Package: go-dt/appinfo


Objections

Why do we need Domain Types at all?!?
Short answer Shared types reduce friction and make codebases interoperate.
Longer answer When two packages both use a domain type like dt.DirPath they exchange values without constant type casting.
Using a 3rd package eliminates dreaded import cycles.
Using dt saves time, reduces bugs, and makes APIs easier to compose across teams.
Minimal adoption Use a single type (for example dt.Filepath) at package boundaries.
Compatibility angle Stable shared types are a stronger guarantee than ad-hoc local types that can drift or be renamed.
Why not define my own types per package?
Short answer You lose the key benefit of domains types: interoperability.
Longer answer Local types fracture the ecosystem because each package invents its own names and helpers.
Local types require constant type casting across packages.
dt aims to be the stable, no (other) dependency. shared vocabulary.
You often must create your own 3rd package to avoid import cycles anyway, why not use dt instead?
Minimal adoption Use dt types at package boundaries, keep internals local.
Compatibility angle Shared stable types reduce breakage at integration points.
This is overkill for small libraries.
Short answer Small libraries benefit most from stable compatibility signals.
Longer answer Small teams often ship faster and have fewer release resources, so breaking changes are more costly.
A small set of stable types reduces downstream churn.
Minimal adoption Use only 1-2 core types and ignore the rest.
Compatibility angle A tiny stable surface is easier to preserve than a large, implicit one.
Why not just use plain strings?
Short answer Types encode intent and reduce mistakes.
Longer answer string does not tell readers or tooling whether the value is a filename, a URL, or an identifier.
dt types make intent explicit and enable safe helper methods.
Validating Parse<type>()(<type>,error) funcs for each type make baked-in assumptions explicit and actionable.
Minimal adoption Replace only the most error-prone string fields in public APIs.
Compatibility angle Stable types keep public contracts clear even as internals change.
I do not want to teach new developers a new way.
Short answer Use a small set and let tooling teach the rest.
Longer answer A handful of domain types is easy and obvious to learn.
Method-based API are discoverable in IDEs.
Linters can enforce conventions at the boundaries.
Minimal adoption Use only the types that already map to your domain language.
Start with dt.DirPath and dt.Filepath, for example.
Compatibility angle Clear, stable types reduce downstream friction and support burden.

Governance & Community

dt is very open to collaboration; we are actively seeking it. Our intention is to recruit enough active contributors that governance can eventually move to a dedicated GitHub organization. The aim is a community-led defacto-standard that remains practical, stable, and inclusive.

If you share this vision — whether as a library author, contributor, or just a developer who’s tired of having to use a string type instead of a bespoke domain type becausthe friction is just too great — start or join a discussion and/or submit a pull requestto help drive what dt can become.


License

MIT License — see LICENSE for details.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrMissingSentinel     = errors.New("missing required sentinel error")
	ErrTrailingKey         = errors.New("trailing key without value")
	ErrMisplacedError      = errors.New("error in wrong position")
	ErrInvalidArgumentType = errors.New("invalid argument type")
	ErrOddKeyValueCount    = errors.New("odd number of key-value arguments")
	ErrCrossPackageError   = errors.New("error from different doterr package")
)

Sentinel errors for validation failures

View Source
var (
	ErrPathIsDir               = errors.New("path is a directory")
	ErrPathIsFile              = errors.New("path is a file (not a directory)")
	ErrDoesNotExist            = errors.New("does not exist")
	ErrExists                  = errors.New("exists")
	ErrDirDoesNotExist         = errors.New("dir does not exist")
	ErrDirExists               = errors.New("dir exists")
	ErrFileNotExists           = errors.New("file does not exist")
	ErrFileExists              = errors.New("file exists")
	ErrInvalidEntryStatus      = errors.New("invalid entry status")
	ErrUnclassifiedEntryStatus = errors.New("unclassified entry status")
	ErrUnsupportedEntryType    = errors.New("unsupported entry type")
)
View Source
var (
	ErrInvalidPathSegment  = errors.New("invalid path segment")
	ErrInvalidURLSegment   = errors.New("invalid URL segment")
	ErrInvalidURLSegments  = errors.New("invalid URL segments")
	ErrInvalidIdentifier   = errors.New("invalid identifier")
	ErrFailedTypeAssertion = errors.New("failed type assertion")

	// ErrInvalidForOpen is used when ValidPath()==false
	ErrInvalidForOpen = errors.New("invalid for open")
)
View Source
var (
	ErrFileSystem                      = errors.New("file system error")
	ErrFailedReadingSymlink            = errors.New("failed reading symlink")
	ErrFailedToLoadFile                = errors.New("failed to load file")
	ErrFailedToCopyFile                = errors.New("failed to copy file")
	ErrFailedToMakeDirectory           = errors.New("failed to make directory")
	ErrFailedtoCreateTempFile          = errors.New("failed to create temp file")
	ErrFailedtoCreateFile              = errors.New("failed to create file")
	ErrContainsBackslash               = errors.New("contains slash ('\\')")
	ErrContainsSlash                   = errors.New("contains slash ('/')")
	ErrEmpty                           = errors.New("cannot be empty")
	ErrInvalidPercentEncoding          = errors.New("invalid percent encoding")
	ErrTooLong                         = errors.New("too long")
	ErrUnspecified                     = errors.New("unspecified")
	ErrInvalid                         = errors.New("invalid")
	ErrInvalidDirectory                = errors.New("invalid directory")
	ErrInvalidfileSystemEntryType      = errors.New("invalid file system entry type")
	ErrControlCharacter                = errors.New("control character")
	ErrInvalidCharacter                = errors.New("invalid charnacter")
	ErrTrailingSpace                   = errors.New("trailing space")
	ErrTrailingPeriod                  = errors.New("trailing period")
	ErrReservedDeviceName              = errors.New("reserved device name")
	ErrNotFileOrDirectory              = errors.New("not a file or directory")
	ErrNotDirectory                    = errors.New("not a directory")
	ErrIsAFile                         = errors.New("is a file")
	ErrIsADirectory                    = errors.New("is a directory")
	ErrCannotDetermineWorkingDirectory = errors.New("cannot determine working directory")
)
View Source
var (
	ErrValueIsNil          = errors.New("value is nil")
	ErrInterfaceValueIsNil = errors.New("interface value is nil")
)
View Source
var (
	ErrConnectFailed          = errors.New("failed to connect to database")
	ErrInvalidConnectString   = errors.New("invalid connection string")
	ErrFailedToPingDatabase   = errors.New("failed to ping database")
	ErrFailedToOpenDatabase   = errors.New("failed to open database")
	ErrFailedToExecuteQueries = errors.New("failed to execute query(s)")
)
View Source
var (
	ErrFlagIsRequired       = errors.New("flag is required")
	ErrInvalidDuplicateFlag = errors.New("invalid duplicate flag")
	ErrInvalidFlagName      = errors.New("invalid flag name")
	ErrFlagValidationFailed = errors.New("flag validation failed")
)
View Source
var (
	ErrUnexpectedError = errors.New("unexpected error")
	ErrInternalError   = errors.New("internal error")
)
View Source
var (
	ErrAccessingWorkingDir    = errors.New("error accessing working dir")
	ErrAccessingUserConfigDir = errors.New("error accessing user config dir")
	ErrAccessingCLIConfigDir  = errors.New("error accessing CLI config dir")
	ErrAccessingUserHomeDir   = errors.New("error accessing user home dir")
	ErrAccessingUserCacheDir  = errors.New("error accessing user cache dir")
)
View Source
var ErrInvalidPathSeparator = errors.New("invalid path separator")
View Source
var ErrNotTildePath = errors.New("not a tilde-prefixed path")

Functions

func AppendErr

func AppendErr(errs []error, err error) []error

func CanWrite

func CanWrite(path EntryPath) (canWrite bool, err error)

func ChangeDirTimes

func ChangeDirTimes(dp DirPath, atime time.Time, mtime time.Time) error

func ChangeFileTimes

func ChangeFileTimes(fp Filepath, atime time.Time, mtime time.Time) error

func Chtimes

func Chtimes[T ~string](path T, atime time.Time, mtime time.Time) error

func CloseOrLog

func CloseOrLog(c io.Closer)

func CombineErrs

func CombineErrs(errs []error) error

CombineErrs bundles a slice of errors into a single composite error that unwraps to its members. Order is preserved and nils are skipped. Returns nil for an empty/fully-nil slice, or the sole error when there is exactly one.

func CreateFile

func CreateFile(fp Filepath) (*os.File, error)

func CreateTemp

func CreateTemp(dp DirPath, pattern string) (*os.File, error)

func DirFS

func DirFS(dp DirPath) fs.FS

func EnsureLogger

func EnsureLogger() *slog.Logger

func ErrValue

func ErrValue[T any](err error, key string) (T, bool)

ErrValue extracts a single metadata value by key with type safety. Returns the value and true if found and the value is of type T. Returns the zero value of T and false if not found or type mismatch.

Example:

status, ok := ErrValue[int](err, "http_status")
if ok {
    fmt.Printf("Status: %d\n", status)
}

name, ok := ErrValue[string](err, "parameter_name")

func Errors

func Errors(err error) []error

Errors returns the errors stored on a doterr entry. If err is a doterr entry, returns its errors. If err is a joined error (has Unwrap() []error), scans immediate children left-to-right and returns errors from the first doterr entry found. Otherwise returns nil. The returned slice preserves insertion order and is a copy.

Note: These errors may be sentinel errors (e.g., ErrRepo), custom error types (e.g., *rfc9457.Error), or any other error type stored in the entry.

func FSReadFile

func FSReadFile(fileSys fs.FS, fp Filepath) ([]byte, error)

func FSStat

func FSStat[T ~string](fileSys fs.FS, entry T) (fs.FileInfo, error)

func FSStatDir

func FSStatDir(fileSys fs.FS, dp DirPath) (fs.FileInfo, error)

func FSStatFile

func FSStatFile(fileSys fs.FS, fp Filepath) (fs.FileInfo, error)

func FindErr

func FindErr[T error](err error) (out T, ok bool)

FindErr walks an error tree (including errors.Join trees) and returns the first match for target (via errors.As).

func IndexSegments added in v0.4.0

func IndexSegments[S ~string](s, sep string, index int) S

IndexSegments returns the segment at the given index in a string split by sep. Returns empty string (cast to S) if index is out of bounds or negative.

func JoinSegments added in v0.4.0

func JoinSegments[S ~string](ss []S, sep string) (s S)

JoinSegments returns joined slice of segments

func LogOnError

func LogOnError(err error)

func Logger

func Logger() *slog.Logger

func MkdirAll

func MkdirAll(dp DirPath, mode os.FileMode) error

func MsgErr added in v0.5.0

func MsgErr(msg any) error

MsgErr creates an ad-hoc error message without requiring a sentinel error. This is a convenience for rapid development - use sentinels for production code.

Accepts two forms:

  • MsgErr("message") - creates error with the given message
  • MsgErr(err) - wraps existing error, preserving error chain for errors.Is()

Use this when you don't want to define a sentinel immediately. Future tooling can detect MsgErr usage and suggest/generate appropriate sentinel errors.

For errors with metadata, use NewErr with a sentinel, or wrap with WithErr:

err := MsgErr("config invalid")
err = WithErr(err, "path", configPath)

func NewErr

func NewErr(parts ...any) error

NewErr builds a standalone structured entry (no primary cause inside). Accepted parts:

  • error — sentinel/tag (required: at least one, must be first)
  • KV{Key,Value} — explicit key/value
  • "key", value — implicit pair (value can be any type, including error)
  • error — optional trailing cause (joined last via errors.Join)

Pattern: one or more sentinels (error), then zero or more key-value pairs, then optional trailing cause (error). After the first string key, all remaining args must form valid pairs, except for an optional final error. Returns nil if no meaningful parts are provided after validation. Returns a validation error joined with the partial entry if validation fails.

func ParseTimeDurationEx

func ParseTimeDurationEx(s string) (td time.Duration, err error)

ParseTimeDurationEx parses a string as EITHER a Go duration format (like "3s", "10m", "1h30m") OR as an integer representing seconds.

func ReadFile

func ReadFile(fp Filepath) ([]byte, error)

func RemoveAll

func RemoveAll(dp DirPath) error

func SetLogger

func SetLogger(l *slog.Logger)

func SliceSegments added in v0.4.0

func SliceSegments[S ~string](s, sep string, start, end int) []S

SliceSegments returns a slice of segments from start (inclusive) to end (exclusive) in a string split by sep, similar to string[start:end] slicing. Supports -1 for end to mean "to the last segment". Returns empty slice if indices are invalid (negative start, start >= end, or out of bounds).

func SliceSegmentsScalar added in v0.4.0

func SliceSegmentsScalar[S ~string](s, sep string, start, end int) S

SliceSegmentsScalar returns a scalar (joined) value of segments from start (inclusive) to end (exclusive) in a string split by sep, similar to string[start:end] slicing but returns a joined string. Supports -1 for end to mean "to the last segment". Returns empty string if indices are invalid. Uses a single pass through the string to find byte positions, avoiding allocations.

func SplitSegments added in v0.4.0

func SplitSegments[S ~string](s, sep string) []S

SplitSegments splits a string by sep separator and returns a slice of the specified segment type. It counts separators first to allocate exact capacity, optimizing for GC and heavy usage.

func Stat

func Stat[T ~string](entry T) (os.FileInfo, error)

func StatDir

func StatDir(dp DirPath) (os.FileInfo, error)

func StatFile

func StatFile(fp Filepath) (os.FileInfo, error)

func UnixModeFunc

func UnixModeFunc(ep EntryPath) (mode os.FileMode)

UnixModeFunc provides standard Unix permissions (0755 for directories, 0644 for files)

func WalkDir added in v0.4.0

func WalkDir(root DirPath) iter.Seq2[DirEntry, error]

func WithErr

func WithErr(parts ...any) error

WithErr is a flexible enrichment helper. Typical uses:

// Enrich an existing composite error (err may be an errors.Join tree):
err = WithErr(err, "Foo", 10)

// Build an entry and join a trailing cause in one shot:
err = WithErr("endpoint", ep, ErrTemplate, cause) // 'cause' is last

Behavior:

  1. If the FIRST arg is an error, it is treated as the base error to enrich: • If it is a doterr entry, merge KVs/sentinels into that entry. • If it is a multi-unwrap (errors.Join tree), find the RIGHTMOST doterr entry, merge into it, and rebuild preserving order. • If no doterr entry is found, a new entry will be joined in (see step 3).

  2. After consuming the base (if present), if the LAST remaining arg is an error, it is treated as the CAUSE and joined LAST.

  3. The remaining middle args (if any) are collected into an entry. If we enriched an existing doterr entry in step 1, that merged entry is used; otherwise, a fresh entry is created. If there is a trailing CAUSE from step 2, the result is errors.Join(entry, cause). If there is no cause, the entry is returned.

Note: For inter-function composition, prefer New() with trailing cause:

return NewErr(ErrRepo, "key", val, cause) // cause last

func WriteFile

func WriteFile(fp Filepath, data []byte, mode os.FileMode) error

Types

type Config added in v0.5.0

type Config interface {
	Config()
}

type CopyOptions

type CopyOptions struct {
	Overwrite    bool          // Overwrite existing files
	DestModeFunc EntryModeFunc // Permission callback (nil = preserve source permissions)
}

CopyOptions contains options for the copy operation

type DirEntry added in v0.3.4

type DirEntry struct {
	// Root is the logical root DirPath that was walked.
	// It is exactly what the caller passed to Walk / WalkFS and may be
	// absolute or relative.
	Root DirPath

	// Rel is the path of this entry relative to the fs.FS root / Root.
	// It is always relative.
	Rel RelPath

	// Entry is the underlying fs.DirEntry. It may be nil for entries where
	// fs.WalkDir reported an error before obtaining a DirEntry.
	Entry fs.DirEntry
	// contains filtered or unexported fields
}

DirEntry represents a filesystem entry discovered while walking a DirPath. It wraps fs.DirEntry and uses EntryPath for the entry's path relative to the walked root.

func DirPathRead added in v0.5.0

func DirPathRead(dp DirPath) (des []DirEntry, err error)

func NewDirEntry added in v0.4.0

func NewDirEntry(root DirPath, entry fs.DirEntry) (de DirEntry)

func NewDirEntryWithSkipDir added in v0.5.0

func NewDirEntryWithSkipDir(root DirPath, rel RelPath, skipDir *bool) DirEntry

func (DirEntry) Base added in v0.3.4

func (de DirEntry) Base() EntryPath

Base returns the last path element of Rel as an EntryPath, similar to filepath.Base on the relative string. It does not panic and is valid for both files and directories.

func (DirEntry) DirPath added in v0.4.0

func (de DirEntry) DirPath() DirPath

DirPath returns the entry as a directory path. It is intended for directory entries and will panic if called on a non-directory.

func (DirEntry) EntryPath added in v0.5.0

func (de DirEntry) EntryPath() EntryPath

EntryPath returns the full path for a file or dir entry.

func (DirEntry) Ext added in v0.5.0

func (de DirEntry) Ext() FileExt

func (DirEntry) Filename added in v0.3.4

func (de DirEntry) Filename() Filename

Filename returns the last path element as a Filename. It is intended for file entries and will panic if called on a non-file.

func (DirEntry) Filepath added in v0.5.0

func (de DirEntry) Filepath() Filepath

Filepath returns the full filepath for the trny. It is intended for non-directory entries and will panic if called on a directory.

func (DirEntry) IsDir added in v0.3.4

func (de DirEntry) IsDir() (isDir bool)

IsDir reports whether this DirEntry represents a directory.

func (DirEntry) IsFile added in v0.3.4

func (de DirEntry) IsFile() (isFile bool)

IsFile reports whether this DirEntry represents a regular file (non-dir).

func (DirEntry) PathSegment added in v0.3.4

func (de DirEntry) PathSegment() PathSegment

PathSegment returns the last path element as a PathSegment. It is intended for directory entries and will panic if called on a non-directory.

func (DirEntry) SkipDir added in v0.3.4

func (de DirEntry) SkipDir()

SkipDir causes the current directory (if this DirEntry represents a directory during a Walk) to be skipped, analogous to returning fs.SkipDir from a WalkDir callback.

type DirPath

type DirPath string

DirPath represents an absolute or relative filesystem directory path.

It provides helper methods for working with directories while preserving type safety and semantic clarity over raw strings. A zero value is valid but does not refer to any real directory.

func DirPathJoin

func DirPathJoin[T1, T2 ~string](a T1, b T2) DirPath

func DirPathJoin3

func DirPathJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) DirPath

func DirPathJoin4

func DirPathJoin4[T1, T2, T3, T4 ~string](a T1, b T2, c T3, d T4) DirPath

func DirPathJoin5

func DirPathJoin5[T1, T2, T3, T4, T5 ~string](a T1, b T2, c T3, d T4, e T5) DirPath

func Getwd

func Getwd() (DirPath, error)

func MkdirTemp

func MkdirTemp(dp DirPath, pattern string) (DirPath, error)

func ParseDirPath

func ParseDirPath(s string) (dp DirPath, err error)

func ParseDirPaths

func ParseDirPaths(dirs []string) (dps []DirPath, err error)

func TempDir added in v0.2.3

func TempDir() DirPath

func UserCacheDir

func UserCacheDir() (DirPath, error)

func UserConfigDir

func UserConfigDir() (DirPath, error)

func UserHomeDir

func UserHomeDir() (DirPath, error)

func (DirPath) Abs

func (dp DirPath) Abs() (DirPath, error)

func (DirPath) Base

func (dp DirPath) Base() PathSegment

func (DirPath) CanWrite

func (dp DirPath) CanWrite() (bool, error)

func (DirPath) Chmod

func (dp DirPath) Chmod(mode os.FileMode) error

func (DirPath) Clean

func (dp DirPath) Clean() DirPath

func (DirPath) Contains

func (dp DirPath) Contains(part any) bool

func (DirPath) Dir

func (dp DirPath) Dir() DirPath

func (DirPath) DirFS

func (dp DirPath) DirFS() fs.FS

func (DirPath) EnsureExists

func (dp DirPath) EnsureExists() (err error)

EnsureExists verifies that the directory exists, creating it and any missing parent directories as needed.

If the path already exists as a directory, EnsureExists is a no-op. If the path exists as a file, it returns ErrPathIsFile. Any other filesystem error is returned as-is.

func (DirPath) EnsureTrailSep

func (dp DirPath) EnsureTrailSep() DirPath

func (DirPath) ErrKV added in v0.5.0

func (dp DirPath) ErrKV() ErrKV
func (dp DirPath) EvalSymlinks() (_ DirPath, err error)

func (DirPath) Exists

func (dp DirPath) Exists() (exists bool, err error)

func (DirPath) Expand added in v0.5.0

func (dp DirPath) Expand() (_ DirPath, err error)

func (DirPath) HasDotDotPrefix added in v0.2.3

func (dp DirPath) HasDotDotPrefix() bool

func (DirPath) HasPrefix added in v0.4.0

func (dp DirPath) HasPrefix(prefix DirPath) bool

func (DirPath) HasSuffix added in v0.4.0

func (dp DirPath) HasSuffix(suffix string) bool

func (DirPath) IsAbs

func (dp DirPath) IsAbs() bool

func (DirPath) IsTidlePath added in v0.5.0

func (dp DirPath) IsTidlePath() bool

func (DirPath) Join

func (dp DirPath) Join(elems ...any) DirPath

func (DirPath) Lstat added in v0.5.0

func (dp DirPath) Lstat(fileSys ...fs.FS) (os.FileInfo, error)

func (DirPath) MkdirAll

func (dp DirPath) MkdirAll(mode os.FileMode) error

func (DirPath) Normalize added in v0.5.0

func (dp DirPath) Normalize() (DirPath, error)

Normalize expands a leading "~" to the current user's home directory (when it uses the correct OS path separator), then returns an absolute directory path.

func (DirPath) ReadDir

func (dp DirPath) ReadDir() ([]os.DirEntry, error)

func (DirPath) Rel

func (dp DirPath) Rel(baseDir DirPath) (PathSegments, error)

func (DirPath) Remove added in v0.5.0

func (dp DirPath) Remove() error

func (DirPath) RemoveAll

func (dp DirPath) RemoveAll() error

func (DirPath) Stat

func (dp DirPath) Stat(fileSys ...fs.FS) (os.FileInfo, error)

func (DirPath) Status

func (dp DirPath) Status(flags ...EntryStatusFlags) (status EntryStatus, err error)

func (DirPath) String

func (dp DirPath) String() string

func (DirPath) ToLower added in v0.5.0

func (dp DirPath) ToLower() DirPath

func (DirPath) ToSlash added in v0.5.0

func (dp DirPath) ToSlash() DirPath

func (DirPath) ToTilde added in v0.5.0

func (dp DirPath) ToTilde() (tdp TildeDirPath, err error)

func (DirPath) ToUpper added in v0.5.0

func (dp DirPath) ToUpper() DirPath

func (DirPath) TrimPrefix added in v0.4.0

func (dp DirPath) TrimPrefix(prefix DirPath) DirPath

func (DirPath) TrimSuffix added in v0.4.0

func (dp DirPath) TrimSuffix(TrimSuffix string) DirPath

func (DirPath) VolumeName

func (dp DirPath) VolumeName() VolumeName

func (DirPath) Walk added in v0.3.4

func (dp DirPath) Walk() iter.Seq2[DirEntry, error]

Walk walks the filesystem rooted at d using d.DirFS() and yields all entries as DirEntry values together with any per-entry errors encountered.

func (DirPath) WalkDirs added in v0.3.4

func (dp DirPath) WalkDirs() iter.Seq2[DirEntry, error]

WalkDirs walks using d.DirFS() and yields only entries that represent directories.

func (DirPath) WalkDirsFS added in v0.3.4

func (dp DirPath) WalkDirsFS(fsys fs.FS) iter.Seq2[DirEntry, error]

WalkDirsFS walks the provided fsys and yields only entries that represent directories.

func (DirPath) WalkFS added in v0.3.4

func (dp DirPath) WalkFS(fsys fs.FS) iter.Seq2[DirEntry, error]

WalkFS walks the provided fsys (typically obtained from d.DirFS()) starting at "." and yields all entries as DirEntry values together with any per-entry errors encountered.

This implementation is non-recursive and uses fs.ReadDir internally so that it can correctly honor the iterator contract: once the caller stops iteration (yield returns false), WalkFS will not call yield again.

func (DirPath) WalkFiles added in v0.3.4

func (dp DirPath) WalkFiles() iter.Seq2[DirEntry, error]

WalkFiles walks using d.DirFS() and yields only entries that represent regular files.

func (DirPath) WalkFilesFS added in v0.3.4

func (dp DirPath) WalkFilesFS(fsys fs.FS) iter.Seq2[DirEntry, error]

WalkFilesFS walks the provided fsys and yields only entries that represent regular files.

type EntryModeFunc

type EntryModeFunc func(ep EntryPath) os.FileMode

EntryModeFunc is a callback that returns the desired file mode for a destination path. Return 0 to preserve the source file's permissions.

type EntryPath

type EntryPath string

EntryPath can be a Filepath or a DirPath

func EntryPathJoin

func EntryPathJoin[T1, T2 ~string](a T1, b T2) EntryPath

func EntryPathJoin3

func EntryPathJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) EntryPath

func EntryPathJoin4

func EntryPathJoin4[T1, T2, T3, T4 ~string](a T1, b T2, c T3, d T4) EntryPath

func EntryPathJoin5

func EntryPathJoin5[T1, T2, T3, T4, T5 ~string](a T1, b T2, c T3, d T4, e T5) EntryPath

func (EntryPath) Abs

func (ep EntryPath) Abs() (EntryPath, error)

func (EntryPath) Base

func (ep EntryPath) Base() PathSegment

func (EntryPath) Clean added in v0.5.0

func (ep EntryPath) Clean() EntryPath

func (EntryPath) Contains

func (ep EntryPath) Contains(substr any) bool

Contains checks if ep contains the given substring. Accepts: string, DirPath, Filepath, EntryPath, PathSegment, or fmt.Stringer Panics on unsupported types.

func (EntryPath) Dir

func (ep EntryPath) Dir() DirPath

func (EntryPath) EnsureTrailSep

func (ep EntryPath) EnsureTrailSep() EntryPath

EnsureTrailSep returns ep with exactly one trailing path separator when appropriate for the platform. It does not modify an empty string.

func (ep EntryPath) EvalSymlinks() (_ EntryPath, err error)

func (EntryPath) Expand added in v0.5.0

func (ep EntryPath) Expand() (out EntryPath, err error)

func (EntryPath) HasDotDotPrefix added in v0.2.3

func (ep EntryPath) HasDotDotPrefix() bool

HasDotDotPrefix reports whether p, interpreted as a relative path, starts with a ".." segment (e.g. ".." or "../foo" or "..\foo"). It does NOT treat names like "..foo" as having a dot-dot prefix.

func (EntryPath) HasSuffix

func (ep EntryPath) HasSuffix(suffix DirPath) bool

func (EntryPath) IsAbs added in v0.5.0

func (ep EntryPath) IsAbs() bool

func (EntryPath) IsFile added in v0.5.0

func (ep EntryPath) IsFile() bool

func (EntryPath) Join

func (ep EntryPath) Join(elems ...any) EntryPath

func (EntryPath) Lstat

func (ep EntryPath) Lstat(fileSys ...fs.FS) (os.FileInfo, error)
func (ep EntryPath) Readlink() (target EntryPath, err error)

Readlink returns the target of the symlink referred to by fp.

It returns the resolved target as a EntryPath. If fp is not a symlink, it returns an empty EntryPath and a non-nil error from os.Readlink. On most systems the returned target is relative to the directory containing fp, not an absolute path.

func (EntryPath) Stat

func (ep EntryPath) Stat(fileSys ...fs.FS) (fs.FileInfo, error)

func (EntryPath) Status

func (ep EntryPath) Status(flags ...EntryStatusFlags) (status EntryStatus, err error)

Status classifies the filesystem entry referred to by fp.

It returns IsMissingEntry when the entry does not exist (err == nil). It returns IsEntryError for all other filesystem errors (err != nil). By default it follows symlinks (like os.Stat). To inspect the entry itself, pass FlagDontFollowSymlinks.

On platforms that don't support certain kinds (e.g., sockets/devices on Windows), those statuses will never be returned.

func (EntryPath) VolumeName

func (ep EntryPath) VolumeName() VolumeName

type EntryStatus

type EntryStatus uint8

EntryStatus represents the classification of a filesystem entry.

It describes whether a given path refers to a file, directory, missing entry, or another type of object such as a symlink, socket, or device.

The zero value (IsInvalidEntryStatus) indicates an uninitialized or invalid status. IsEntryError denotes that an underlying filesystem error occurred; in that case, the accompanying error value from Status or LstatStatus provides additional detail.

const (
	// IsInvalidEntryStatus is the zero value and indicates an uninitialized
	// or otherwise invalid EntryStatus.
	IsInvalidEntryStatus EntryStatus = iota

	// IsEntryError indicates a filesystem error occurred; the returned error
	// from Status or LstatStatus will contain the details.
	IsEntryError

	// IsMissingEntry indicates the entry does not exist (fs.ErrNotExist).
	IsMissingEntry

	// IsFileEntry indicates a regular file.
	IsFileEntry

	// IsDirEntry indicates a directory.
	IsDirEntry

	IsSymlinkEntry
	IsSocketEntry
	IsPipeEntry
	IsDeviceEntry

	// IsUnclassifiedEntryStatus indicates some other kind of filesystem entry such as
	// a symlink, socket, device, or named pipe.
	IsUnclassifiedEntryStatus
)

func (EntryStatus) String

func (s EntryStatus) String() string

String returns a human-readable representation of the EntryStatus.

It is primarily intended for diagnostic output and logging; program logic should use the EntryStatus constants directly.

type EntryStatusFlags

type EntryStatusFlags uint32

EntryStatusFlags controls optional classification behavior. The zero value is safe and means "follow symlinks" (os.Stat).

const (
	// DontFollowSymlinks causes Status to inspect the entry itself
	// (os.Lstat) instead of following symlinks.
	DontFollowSymlinks EntryStatusFlags = 1 << iota
)

type ErrKV added in v0.5.0

type ErrKV interface {
	Key() string
	Value() any
}

ErrKV represents a key/value metadata pair. Keys are preserved in insertion order, and values may be of any type.

func AnyKV added in v0.5.0

func AnyKV(key string, value any) ErrKV

AnyKV creates a KV with any value type. Use this for custom types or when the specific type constructor doesn't exist.

func AppendKV added in v0.5.0

func AppendKV(kvs []ErrKV, parts ...any) []ErrKV

AppendKV appends key-value pairs to a slice of KV values. It accepts variadic arguments in three forms:

  1. Individual KV values: AppendKV(kvs, StringKV("foo", "bar"))
  2. String key-value pairs: AppendKV(kvs, "foo", "bar")
  3. Lazy ErrKV functions: AppendKV(kvs, func()ErrKV{ return StringKV("expensive", compute()) })

This function is useful for accumulating metadata throughout a function before creating an error:

var kvs []ErrKV
kvs = AppendKV(kvs, "user_id", userID)
if complexCondition {
    kvs = AppendKV(kvs, "reason", "complex")
}
return NewErr(ErrFailed, kvs, cause)

String key-value pairs must come in even counts (odd counts panic in debug mode). Lazy functions (func()ErrKV) are wrapped and not evaluated until error creation.

func BoolKV added in v0.5.0

func BoolKV(key string, value bool) ErrKV

BoolKV creates a KV with a bool value.

func ErrMeta

func ErrMeta(err error) []ErrKV

ErrMeta returns the key/value pairs stored on all doterr entries in the error tree. If err is a doterr entry, returns its metadata. If err is a joined error (has Unwrap() []error), scans all children recursively and collects metadata from all doterr entries found, preserving order. Otherwise returns nil. The returned slice preserves insertion order across all entries.

func ErrorKV added in v0.5.0

func ErrorKV(key string, value error) ErrKV

ErrorKV creates a KV with an error value. Use this when you want to include an error as metadata (not as a cause).

func Float64KV added in v0.5.0

func Float64KV(key string, value float64) ErrKV

Float64KV creates a KV with a float64 value.

func Int64KV added in v0.5.0

func Int64KV(key string, value int64) ErrKV

Int64KV creates a KV with an int64 value.

func IntKV added in v0.5.0

func IntKV(key string, value int) ErrKV

IntKV creates a KV with an int value.

func StringKV added in v0.5.0

func StringKV(key, value string) ErrKV

StringKV creates a KV with a string value.

type FileExt

type FileExt string

FileExt is a filename extension with leading period ('.')

type Filename

type Filename string

Filename with name and extension, if exists, but no path component

func (Filename) Ext

func (fn Filename) Ext() FileExt

type Filepath

type Filepath string

Filepath is an absolute or relativate filepath with filename including extension if applicable

func FilepathJoin

func FilepathJoin[T1, T2 ~string](a T1, b T2) Filepath

func FilepathJoin3

func FilepathJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) Filepath

func FilepathJoin4

func FilepathJoin4[T1, T2, T3, T4 ~string](a T1, b T2, c T3, d T4) Filepath

func FilepathJoin5

func FilepathJoin5[T1, T2, T3, T4, T5 ~string](a T1, b T2, c T3, d T4, e T5) Filepath

func ParseFilepath

func ParseFilepath(s string) (fp Filepath, err error)

func (Filepath) Abs

func (fp Filepath) Abs() (Filepath, error)

func (Filepath) Base

func (fp Filepath) Base() Filename

func (Filepath) CopyTo

func (fp Filepath) CopyTo(dest Filepath, opts *CopyOptions) (err error)

CopyTo copies the file to the destination filepath with optional permission control

func (Filepath) CopyToDir

func (fp Filepath) CopyToDir(dest DirPath, opts *CopyOptions) (err error)

CopyToDir copies the file to the destination directory path with optional permission control

func (Filepath) Create

func (fp Filepath) Create() (*os.File, error)

func (Filepath) Dir

func (fp Filepath) Dir() DirPath
func (fp Filepath) EvalSymlinks() (_ Filepath, err error)

func (Filepath) Exists

func (fp Filepath) Exists() (exists bool, err error)

func (Filepath) Expand added in v0.5.0

func (fp Filepath) Expand() (_ Filepath, err error)

func (Filepath) Ext

func (fp Filepath) Ext() FileExt

func (Filepath) HasDotDotPrefix added in v0.2.3

func (fp Filepath) HasDotDotPrefix() bool

func (Filepath) HasPrefix

func (fp Filepath) HasPrefix(prefix DirPath) bool

func (Filepath) HasSuffix

func (fp Filepath) HasSuffix(suffix DirPath) bool

func (Filepath) Join

func (fp Filepath) Join(elems ...any) Filepath

func (Filepath) Lstat

func (fp Filepath) Lstat() (os.FileInfo, error)

func (Filepath) Open

func (fp Filepath) Open() (*os.File, error)

func (Filepath) OpenFile

func (fp Filepath) OpenFile(flag int, mode os.FileMode) (*os.File, error)

func (Filepath) ReadFile

func (fp Filepath) ReadFile(fileSys ...fs.FS) ([]byte, error)
func (fp Filepath) Readlink() (target Filepath, err error)

Readlink returns the target of the symlink referred to by fp.

It returns the resolved target as a Filepath. If fp is not a symlink, it returns an empty Filepath and a non-nil error from os.Readlink. On most systems the returned target is relative to the directory containing fp, not an absolute path.

func (Filepath) Rel

func (fp Filepath) Rel(baseDir DirPath) (RelFilepath, error)

func (Filepath) Remove

func (fp Filepath) Remove() error

func (Filepath) Stat

func (fp Filepath) Stat(fileSys ...fs.FS) (os.FileInfo, error)

func (Filepath) Status

func (fp Filepath) Status(flags ...EntryStatusFlags) (status EntryStatus, err error)

Status classifies the filesystem entry referred to by fp.

It returns IsMissingEntry when the entry does not exist (err == nil). It returns IsEntryError for all other filesystem errors (err != nil). By default it follows symlinks (like os.Stat). To inspect the entry itself, pass FlagDontFollowSymlinks.

On platforms that don't support certain kinds (e.g., sockets/devices on Windows), those statuses will never be returned.

func (Filepath) StringLike

func (Filepath) StringLike()

func (Filepath) ValidPath

func (fp Filepath) ValidPath() bool

func (Filepath) WriteFile

func (fp Filepath) WriteFile(data []byte, mode os.FileMode) error

type FilepathGetter added in v0.3.0

type FilepathGetter interface {
	Filepath() Filepath
}

type Identifier

type Identifier string

func ParseIdentifier added in v0.4.0

func ParseIdentifier(s string) (id Identifier, err error)

type InternetDomain added in v0.4.0

type InternetDomain string

InternetDomain is used for internet domains like google.com or www.example.com.

type PathSegment

type PathSegment string

func (PathSegment) Contains

func (ps PathSegment) Contains(part any) bool

func (PathSegment) Exists added in v0.3.3

func (ps PathSegment) Exists() (exists bool, err error)

func (PathSegment) HasDotDotPrefix added in v0.2.3

func (ps PathSegment) HasDotDotPrefix() bool

func (PathSegment) MkdirAll added in v0.3.3

func (ps PathSegment) MkdirAll(mode os.FileMode) error

func (PathSegment) Status added in v0.3.3

func (ps PathSegment) Status(flags ...EntryStatusFlags) (status EntryStatus, err error)

Status classifies the filesystem entry referred to by fp.

It returns IsMissingEntry when the entry does not exist (err == nil). It returns IsEntryError for all other filesystem errors (err != nil). By default it follows symlinks (like os.Stat). To inspect the entry itself, pass FlagDontFollowSymlinks.

On platforms that don't support certain kinds (e.g., sockets/devices on Windows), those statuses will never be returned.

func (PathSegment) TrimPrefix added in v0.4.0

func (ps PathSegment) TrimPrefix(prefix DirPath) PathSegment

func (PathSegment) TrimSuffix added in v0.4.0

func (ps PathSegment) TrimSuffix(TrimSuffix string) PathSegment

func (PathSegment) WriteFile added in v0.3.3

func (ps PathSegment) WriteFile(data []byte, mode os.FileMode) error

type PathSegments

type PathSegments string

PathSegments is one or more path segments for a filesystem path

func ParentPath added in v0.5.0

func ParentPath() PathSegments

func PathSegmentsJoin added in v0.4.0

func PathSegmentsJoin[T1, T2 ~string](a T1, b T2) PathSegments

func PathSegmentsJoin3 added in v0.4.0

func PathSegmentsJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) PathSegments

func PathSegmentsJoin4 added in v0.4.0

func PathSegmentsJoin4[T1, T2, T3, T4 ~string](a T1, b T2, c T3, d T4) PathSegments

func PathSegmentsJoin5 added in v0.4.0

func PathSegmentsJoin5[T1, T2, T3, T4, T5 ~string](a T1, b T2, c T3, d T4, e T5) PathSegments

func (PathSegments) Contains added in v0.5.0

func (pss PathSegments) Contains(part any) bool

func (PathSegments) Escapes added in v0.5.0

func (pss PathSegments) Escapes() (escapes bool)

func (PathSegments) FromSlash added in v0.5.0

func (pss PathSegments) FromSlash() PathSegments

func (PathSegments) HasPrefix added in v0.5.0

func (pss PathSegments) HasPrefix(prefix PathSegments) bool

func (PathSegments) HasSuffix added in v0.5.0

func (pss PathSegments) HasSuffix(suffix string) bool

func (PathSegments) LastIndex added in v0.4.0

func (pss PathSegments) LastIndex(sep string) int

func (PathSegments) Normalize added in v0.5.0

func (pss PathSegments) Normalize() PathSegments

Normalize returns a consistent format given different inputs when represent the same path

func (PathSegments) Segment added in v0.4.0

func (pss PathSegments) Segment(index int) PathSegment

Segment returns the segment at the given index in the path. Returns empty PathSegment if index is out of bounds or negative.

func (PathSegments) Segments

func (pss PathSegments) Segments() []PathSegment

Segments returns all segments of the path, same as Split.

func (PathSegments) Slice added in v0.4.0

func (pss PathSegments) Slice(start, end int) []PathSegment

Slice returns segments from start (inclusive) to end (exclusive), similar to string[start:end] slicing.

func (PathSegments) SliceScalar added in v0.4.0

func (pss PathSegments) SliceScalar(start, end int) PathSegments

SliceScalar returns a scalar (joined) value of segments from start (inclusive) to end (exclusive), similar to string[start:end] slicing but returns a joined string using the OS separator. Supports -1 for end to mean "to the last segment".

func (PathSegments) Split added in v0.2.3

func (pss PathSegments) Split() []PathSegment

Split returns all segments of the path separated by the OS separator as a slice of PathSegment.

func (PathSegments) ToLower added in v0.5.0

func (pss PathSegments) ToLower() PathSegments

func (PathSegments) ToSlash added in v0.5.0

func (pss PathSegments) ToSlash() PathSegments

func (PathSegments) ToUpper added in v0.5.0

func (pss PathSegments) ToUpper() PathSegments

func (PathSegments) TrimPrefix added in v0.5.0

func (pss PathSegments) TrimPrefix(prefix PathSegments) PathSegments

func (PathSegments) TrimSpace added in v0.5.0

func (pss PathSegments) TrimSpace() PathSegments

func (PathSegments) TrimSuffix added in v0.5.0

func (pss PathSegments) TrimSuffix(TrimSuffix string) PathSegments

func (PathSegments) UpperFirst

func (pss PathSegments) UpperFirst() PathSegments

type RelDirPath added in v0.5.0

type RelDirPath = PathSegments

type RelFilepath

type RelFilepath string

RelFilepath is an relativate filepath with filename including extension if applicable

func RelFilepathJoin

func RelFilepathJoin[T1, T2 ~string](a T1, b T2) RelFilepath

func RelFilepathJoin3

func RelFilepathJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) RelFilepath

func RelFilepathJoin4

func RelFilepathJoin4[T1, T2, T3, T4 ~string](a T1, b T2, c T3, d T4) RelFilepath

func RelFilepathJoin5

func RelFilepathJoin5[T1, T2, T3, T4, T5 ~string](a T1, b T2, c T3, d T4, e T5) RelFilepath

func (RelFilepath) Base

func (fp RelFilepath) Base() Filename

func (RelFilepath) Dir

func (fp RelFilepath) Dir() DirPath

func (RelFilepath) Exists added in v0.3.2

func (fp RelFilepath) Exists() (exists bool, err error)

func (RelFilepath) ReadFile

func (fp RelFilepath) ReadFile(fileSys ...fs.FS) ([]byte, error)

func (RelFilepath) Rel added in v0.3.2

func (fp RelFilepath) Rel(baseDir DirPath) (RelFilepath, error)

func (RelFilepath) Stat

func (fp RelFilepath) Stat(fileSys ...fs.FS) (os.FileInfo, error)

func (RelFilepath) Status added in v0.3.2

func (fp RelFilepath) Status(flags ...EntryStatusFlags) (status EntryStatus, err error)

Status classifies the filesystem entry referred to by fp.

It returns IsMissingEntry when the entry does not exist (err == nil). It returns IsEntryError for all other filesystem errors (err != nil). By default it follows symlinks (like os.Stat). To inspect the entry itself, pass FlagDontFollowSymlinks.

On platforms that don't support certain kinds (e.g., sockets/devices on Windows), those statuses will never be returned.

func (RelFilepath) ValidPath

func (fp RelFilepath) ValidPath() bool

func (RelFilepath) WriteFile added in v0.3.2

func (fp RelFilepath) WriteFile(data []byte, mode os.FileMode) error

type RelPath added in v0.5.0

type RelPath string

RelPath can be a RelFilepath or a PathSegments

func (RelPath) Abs added in v0.5.0

func (rp RelPath) Abs() (RelPath, error)

func (RelPath) Base added in v0.5.0

func (rp RelPath) Base() PathSegment

func (RelPath) Contains added in v0.5.0

func (rp RelPath) Contains(substr any) bool

Contains checks if ep contains the given substring. Accepts: string, DirPath, Filepath, RelPath, PathSegment, or fmt.Stringer Panics on unsupported types.

func (RelPath) Dir added in v0.5.0

func (rp RelPath) Dir() DirPath

func (RelPath) HasSuffix added in v0.5.0

func (rp RelPath) HasSuffix(suffix DirPath) bool

func (RelPath) Join added in v0.5.0

func (rp RelPath) Join(elems ...any) RelPath

func (RelPath) Lstat added in v0.5.0

func (rp RelPath) Lstat() (os.FileInfo, error)
func (rp RelPath) Readlink() (target RelPath, err error)

Readlink returns the target of the symlink referred to by fp.

It returns the resolved target as a RelPath. If fp is not a symlink, it returns an empty RelPath and a non-nil error from os.Readlink. On most systems the returned target is relative to the directory containing fp, not an absolute path.

func (RelPath) Stat added in v0.5.0

func (rp RelPath) Stat(fileSys ...fs.FS) (fs.FileInfo, error)

func (RelPath) Status added in v0.5.0

func (rp RelPath) Status(flags ...EntryStatusFlags) (status EntryStatus, err error)

Status classifies the filesystem entry referred to by fp.

It returns IsMissingEntry when the entry does not exist (err == nil). It returns IsEntryError for all other filesystem errors (err != nil). By default it follows symlinks (like os.Stat). To inspect the entry itself, pass FlagDontFollowSymlinks.

On platforms that don't support certain kinds (e.g., sockets/devices on Windows), those statuses will never be returned.

func (RelPath) VolumeName added in v0.5.0

func (rp RelPath) VolumeName() VolumeName

type TildeDirPath added in v0.5.0

type TildeDirPath string

func ParseTildeDirPath added in v0.5.0

func ParseTildeDirPath(s string) (tdp TildeDirPath, err error)

func TildeDirPathJoin added in v0.5.0

func TildeDirPathJoin[T1, T2 ~string](a T1, b T2) TildeDirPath

func (TildeDirPath) Expand added in v0.5.0

func (tdp TildeDirPath) Expand() (dp DirPath, err error)

type TimeFormat added in v0.4.0

type TimeFormat string

TimeFormat controls how timestamps are rendered: e.g. "2006-01-02".

type URL

type URL string

URL is a string that contains a syntactically valid Uniform Resource Locator A valid URL would be parsed without error by net/url.URL.Parse().

func ParseURL

func ParseURL(s string) (u URL, err error)

func URLJoin added in v0.4.0

func URLJoin[T1, T2 ~string](a T1, b T2) URL

func URLJoin3 added in v0.4.0

func URLJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) URL

func URLJoin4 added in v0.4.0

func URLJoin4[T1, T2, T3, T4 ~string](a T1, b T2, c T3, d T4) URL

func URLJoin5 added in v0.4.0

func URLJoin5[T1, T2, T3, T4, T5 ~string](a T1, b T2, c T3, d T4, e T5) URL

func (URL) GET

func (u URL) GET(c *http.Client) (resp *http.Response, err error)

GET performs an HTTP get on the URL receiver given its

func (URL) HTTPGet

func (u URL) HTTPGet(c *http.Client) (resp *http.Response, err error)

func (URL) Parse added in v0.4.0

func (u URL) Parse() (*url.URL, error)

type URLSegment added in v0.4.0

type URLSegment string

func ParseURLSegment added in v0.5.0

func ParseURLSegment(s string) (uss URLSegment, err error)

func (URLSegment) Contains added in v0.4.0

func (ps URLSegment) Contains(part any) bool

func (URLSegment) HasDotDotPrefix added in v0.4.0

func (ps URLSegment) HasDotDotPrefix() bool

type URLSegments added in v0.4.0

type URLSegments string

URLSegments is one or more path segments for a filepath, dir path, or URL

func ParseURLSegments added in v0.4.0

func ParseURLSegments(s string) (uss URLSegments, err error)

func URLSegmentsJoin added in v0.4.0

func URLSegmentsJoin[T1, T2 ~string](a T1, b T2) URLSegments

func URLSegmentsJoin3 added in v0.4.0

func URLSegmentsJoin3[T1, T2, T3 ~string](a T1, b T2, c T3) URLSegments

func URLSegmentsJoin4 added in v0.4.0

func URLSegmentsJoin4[T1, T2, T3, T4 ~string](a T1, b T2, c T3, d T4) URLSegments

func URLSegmentsJoin5 added in v0.4.0

func URLSegmentsJoin5[T1, T2, T3, T4, T5 ~string](a T1, b T2, c T3, d T4, e T5) URLSegments

func (URLSegments) Base added in v0.4.0

func (uss URLSegments) Base() URLSegment

func (URLSegments) LastIndex added in v0.4.0

func (uss URLSegments) LastIndex(sep string) int

func (URLSegments) Segment added in v0.4.0

func (uss URLSegments) Segment(index int) URLSegment

func (URLSegments) Segments added in v0.4.0

func (uss URLSegments) Segments() []URLSegment

func (URLSegments) Slice added in v0.4.0

func (uss URLSegments) Slice(start, end int) []URLSegment

func (URLSegments) SliceScalar added in v0.4.0

func (uss URLSegments) SliceScalar(start, end int, sep string) URLSegment

func (URLSegments) Split added in v0.4.0

func (uss URLSegments) Split() []URLSegment

type Version

type Version string

Version is a string uses for a software version. It is mainly without constraint as people have defined versions in many different ways over time.

type VolumeName

type VolumeName string

VolumeName returns the name of the mounted volume on Windows. It might be "C:" or "\\server\share". On other platforms it is always an empty string.

Directories

Path Synopsis
appinfo module
de module
dtglob module
dtx module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL