1/**
2 * Node-backed provider for Effect's `Path` service.
3 *
4 * This module turns Node's `node:path` and `node:url` APIs into `Path` layers.
5 * `layer` uses the host platform path implementation, while `layerPosix` and
6 * `layerWin32` provide fixed POSIX and Windows variants. All three layers also
7 * include helpers for converting between file paths and file URLs.
8 *
9 * @since 4.0.0
10 */
11import * as Effect from "effect/Effect"
12import * as Layer from "effect/Layer"
13import { Path, TypeId } from "effect/Path"
14import { BadArgument } from "effect/PlatformError"
15import * as NodePath from "node:path"
16import * as NodeUrl from "node:url"
17
18const fileUrlOps = (windows: boolean | undefined) => ({
19 fromFileUrl: (url: URL): Effect.Effect<string, BadArgument> =>
20 Effect.try({
21 try: () => NodeUrl.fileURLToPath(url, { windows }),
22 catch: (cause) =>
23 new BadArgument({
24 module: "Path",
25 method: "fromFileUrl",
26 cause
27 })
28 }),
29 toFileUrl: (path: string): Effect.Effect<URL, BadArgument> =>
30 Effect.try({
31 try: () => NodeUrl.pathToFileURL(path, { windows }),
32 catch: (cause) =>
33 new BadArgument({
34 module: "Path",
35 method: "toFileUrl",
36 cause
37 })
38 })
39})
40
41/**
42 * Provides the `Path` service using Node's POSIX path implementation plus
43 * file URL conversion helpers.
44 *
45 * @category layers
46 * @since 4.0.0
47 */
48export const layerPosix: Layer.Layer<Path> = Layer.succeed(Path)({
49 [TypeId]: TypeId,
50 ...NodePath.posix,
51 ...fileUrlOps(false)
52})
53
54/**
55 * Provides the `Path` service using Node's Windows path implementation plus
56 * file URL conversion helpers.
57 *
58 * @category layers
59 * @since 4.0.0
60 */
61export const layerWin32: Layer.Layer<Path> = Layer.succeed(Path)({
62 [TypeId]: TypeId,
63 ...NodePath.win32,
64 ...fileUrlOps(true)
65})
66
67/**
68 * Provides the default `Path` service using the host platform's Node path
69 * implementation plus file URL conversion helpers.
70 *
71 * @category layers
72 * @since 4.0.0
73 */
74export const layer: Layer.Layer<Path> = Layer.succeed(Path)({
75 [TypeId]: TypeId,
76 ...NodePath,
77 ...fileUrlOps(undefined)
78})