/** * Provides path operations through the Effect environment. * * The `Path` service works with file system paths without tying code to one * concrete platform module. It exposes common operations such as joining, * normalizing, parsing, formatting, resolving, and converting paths to or from * file URLs. This module includes the service interface, parsed path type, * service tag, runtime marker, and built-in POSIX path layer. * * @stability unstable * @since 4.0.0 */ import * as Context from "./Context.ts"; import * as Effect from "./Effect.ts"; import * as Layer from "./Layer.ts"; import * as Option from "./Option.ts"; import { BadArgument } from "./PlatformError.ts"; /** * Runtime type identifier used to mark implementations of the `Path` service. * * **Details** * * The marker is the exact string stored on `Path` service implementations. * Most code should depend on the `Path` service instead of inspecting this * value directly. * * @see {@link layer} for the built-in POSIX `Path` service layer * * @stability unstable * @category type IDs * @since 4.0.0 */ export declare const TypeId = "~effect/Path"; /** * Defines the service interface for platform-specific path manipulation. * * **When to use** * * Use to depend on path operations through the Effect environment instead of a * concrete host path module. * * **Details** * * The service exposes operations for joining, normalizing, parsing, * formatting, and converting file system paths. URL conversion methods return * `Effect`s because invalid file URLs or paths can fail with `BadArgument`. * * `resolveWithin(root, input)` resolves a relative `input` beneath `root` and * returns `Option.none()` when the result would leave the root or when `input` * has its own root (an absolute path, or a Windows drive or UNC prefix). The * root itself is allowed. The check is lexical: it does not follow symlinks, * so it is not a sandbox on its own. A relative `root` is resolved against the * current working directory, as with `resolve`. * * **Example** (Using path operations) * * ```ts import.meta.vitest * import { Effect, Option, Path } from "effect" * * const program = Effect.gen(function*() { * const path = yield* Path.Path * * return { * joined: path.join("home", "user", "documents"), * normalized: path.normalize("./path/../to/file.txt"), * basename: path.basename("/path/to/file.txt"), * dirname: path.dirname("/path/to/file.txt"), * extname: path.extname("file.txt"), * isAbsolute: path.isAbsolute("/absolute/path"), * name: path.parse("/path/to/file.txt").name, * relative: path.relative("/from/path", "/to/path"), * resolved: path.resolve("/base", "relative", "path"), * within: path.resolveWithin("/base", "../outside") * } * }) * * const result = Effect.runSync(Effect.provide(program, Path.layer)) * result.joined // => "home/user/documents" * result.normalized // => "to/file.txt" * result.basename // => "file.txt" * result.dirname // => "/path/to" * result.extname // => ".txt" * result.isAbsolute // => true * result.name // => "file" * result.relative // => "../../to/path" * result.resolved // => "/base/relative/path" * result.within // => Option.none() * ``` * * @stability unstable * @category services * @since 4.0.0 */ export interface Path { readonly [TypeId]: typeof TypeId; readonly sep: string; readonly basename: (path: string, suffix?: string) => string; readonly dirname: (path: string) => string; readonly extname: (path: string) => string; readonly format: (pathObject: Partial) => string; readonly fromFileUrl: (url: URL) => Effect.Effect; readonly isAbsolute: (path: string) => boolean; readonly join: (...paths: ReadonlyArray) => string; readonly normalize: (path: string) => string; readonly parse: (path: string) => Path.Parsed; readonly relative: (from: string, to: string) => string; readonly resolve: (...pathSegments: ReadonlyArray) => string; readonly resolveWithin: (root: string, input: string) => Option.Option; readonly toFileUrl: (path: string) => Effect.Effect; readonly toNamespacedPath: (path: string) => string; } /** * Namespace containing types associated with the `Path` service. * * **When to use** * * Use to reference types associated with path parsing and formatting. * * **Example** (Working with parsed paths) * * ```ts import.meta.vitest * import { Effect, Path } from "effect" * * // Access types and utilities in the Path namespace * const program = Effect.gen(function*() { * const path = yield* Path.Path * * // Parse a path and get a Path.Parsed object * const parsed = path.parse("/home/user/file.txt") * * // The parsed object conforms to the Path.Parsed interface * const exampleParsed = { * root: "/", * dir: "/home/user", * base: "file.txt", * ext: ".txt", * name: "file" * } * * return [parsed.base, exampleParsed.base] * }) * * Effect.runSync(Effect.provide(program, Path.layer)) // => ["file.txt", "file.txt"] * ``` * * @stability unstable * @since 4.0.0 */ export declare namespace Path { /** * Structured representation of a parsed file system path. * * **When to use** * * Use to model the object form produced by `Path.parse` and consumed by * `Path.format`. * * **Details** * * The fields correspond to the path root, directory, base filename, * extension, and filename without extension, matching the shape consumed by * `Path.format`. * * **Example** (Parsing and formatting paths) * * ```ts import.meta.vitest * import { Effect, Path } from "effect" * * const program = Effect.gen(function*() { * const path = yield* Path.Path * * // Parse a path into its components * const parsed = path.parse("/home/user/documents/file.txt") * // Format a path from its components * const formatted = path.format({ * dir: "/home/user", * name: "newfile", * ext: ".ts" * }) * return { dir: parsed.dir, base: parsed.base, formatted } * }) * * const result = Effect.runSync(Effect.provide(program, Path.layer)) * result.dir // => "/home/user/documents" * result.base // => "file.txt" * result.formatted // => "/home/user/newfile.ts" * ``` * * @category models * @since 4.0.0 */ interface Parsed { readonly root: string; readonly dir: string; readonly base: string; readonly ext: string; readonly name: string; } } /** * Service tag for accessing the current `Path` implementation. * * **When to use** * * Use when you need path operations supplied by an effect's environment. * * **Example** (Providing a custom Path service) * * ```ts import.meta.vitest * import { Effect, Layer, Path } from "effect" * * // Create a custom path implementation * const customPath = Path.make({ * sep: "/", * basename: (path: string, suffix?: string) => { * const base = path.split("/").pop() || "" * return suffix && base.endsWith(suffix) * ? base.slice(0, -suffix.length) * : base * }, * dirname: (path: string) => path.split("/").slice(0, -1).join("/") || "/", * extname: (path: string) => { * const match = path.match(/\.[^.]*$/) * return match ? match[0] : "" * }, * format: (pathObject) => { * const dir = pathObject.dir || "" * const name = pathObject.name || "" * const ext = pathObject.ext || "" * return dir ? `${dir}/${name}${ext}` : `${name}${ext}` * }, * fromFileUrl: (url: URL) => Effect.succeed(url.pathname), * isAbsolute: (path: string) => path.startsWith("/"), * join: (...paths: ReadonlyArray) => paths.join("/"), * normalize: (path: string) => path.replace(/\/+/g, "/"), * parse: (path: string) => ({ * root: path.startsWith("/") ? "/" : "", * dir: path.split("/").slice(0, -1).join("/") || "/", * base: path.split("/").pop() || "", * ext: path.match(/\.[^.]*$/)?.[0] || "", * name: path.split("/").pop()?.replace(/\.[^.]*$/, "") || "" * }), * relative: (from: string, to: string) => to.replace(from, ""), * resolve: (...pathSegments: ReadonlyArray) => pathSegments.join("/"), * toFileUrl: (path: string) => Effect.succeed(new URL(`file://${path}`)), * toNamespacedPath: (path: string) => path * }) * * // Provide the path service * const customPathLayer = Layer.succeed(Path.Path)(customPath) * * const program = Effect.gen(function*() { * const path = yield* Path.Path * return path.join("home", "user", "file.txt") * }) * * // Run with custom path implementation * Effect.runSync(Effect.provide(program, customPathLayer)) // => "home/user/file.txt" * ``` * * @stability unstable * @category services * @since 4.0.0 */ export declare const Path: Context.Service; /** * Creates a `Path` service from platform path operations. * * **When to use** * * Use to build a `Path` implementation, such as a platform layer or a test * double, without implementing the operations that can be derived from the * others. * * **Details** * * Adds the `Path` type marker and derives `resolveWithin` from the provided * `parse`, `resolve`, `relative`, `isAbsolute`, and `sep`, so containment * follows the same platform rules as those operations. * * @see {@link layer} for the built-in POSIX `Path` service layer * * @stability unstable * @category constructors * @since 4.0.0 */ export declare const make: (impl: Omit) => Path; /** * Layer that provides the built-in POSIX `Path` implementation. * * **When to use** * * Use when you need an effect that requires the `Path` service to run with the * built-in POSIX path implementation. * * **Details** * * The layer provides a static service whose separator is `/` and whose * operations use POSIX path semantics. * * @see {@link Path} for accessing the `Path` service from an effect * * @stability unstable * @category layers * @since 4.0.0 */ export declare const layer: Layer.Layer; //# sourceMappingURL=Path.d.ts.map