path-class 0.7.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,39 +1,5 @@
1
- import type { Abortable } from "node:events";
2
- import type { Dirent, ObjectEncodingOptions, OpenMode } from "node:fs";
3
- import { cp, mkdir, rm, writeFile } from "node:fs/promises";
4
- declare function readDirType(options?: (ObjectEncodingOptions & {
5
- withFileTypes?: false | undefined;
6
- recursive?: boolean | undefined;
7
- }) | BufferEncoding | null): Promise<string[]>;
8
- declare function readDirType(options: {
9
- encoding: "buffer";
10
- withFileTypes?: false | undefined;
11
- recursive?: boolean | undefined;
12
- } | "buffer"): Promise<Buffer[]>;
13
- declare function readDirType(options?: (ObjectEncodingOptions & {
14
- withFileTypes?: false | undefined;
15
- recursive?: boolean | undefined;
16
- }) | BufferEncoding | null): Promise<string[] | Buffer[]>;
17
- declare function readDirType(options: ObjectEncodingOptions & {
18
- withFileTypes: true;
19
- recursive?: boolean | undefined;
20
- }): Promise<Dirent[]>;
21
- declare function readDirType(options: {
22
- encoding: "buffer";
23
- withFileTypes: true;
24
- recursive?: boolean | undefined;
25
- }): Promise<Dirent<Buffer>[]>;
26
- declare function readFileType(options?: ({
27
- encoding?: null | undefined;
28
- flag?: OpenMode | undefined;
29
- } & Abortable) | null): Promise<Buffer>;
30
- declare function readFileType(options: ({
31
- encoding: BufferEncoding;
32
- flag?: OpenMode | undefined;
33
- } & Abortable) | BufferEncoding): Promise<string>;
34
- declare function readFileType(options?: (ObjectEncodingOptions & Abortable & {
35
- flag?: OpenMode | undefined;
36
- }) | BufferEncoding | null): Promise<string | Buffer>;
1
+ import { cp, mkdir, rm, symlink, writeFile } from "node:fs/promises";
2
+ import type { lstatType, readDirType, readFileType, statType } from "./modifiedNodeTypes";
37
3
  export declare class Path {
38
4
  #private;
39
5
  /**
@@ -118,6 +84,10 @@ export declare class Path {
118
84
  */
119
85
  writeJSON<T>(data: T, replacer?: Parameters<typeof JSON.stringify>[1], space?: Parameters<typeof JSON.stringify>[2]): Promise<Path>;
120
86
  readDir: typeof readDirType;
87
+ /** Returns the destination path. */
88
+ symlink(target: string | URL | Path, type?: Parameters<typeof symlink>[2]): Promise<Path>;
89
+ stat: typeof statType;
90
+ lstat: typeof lstatType;
121
91
  static get homedir(): Path;
122
92
  static xdg: {
123
93
  cache: Path;
@@ -152,4 +122,3 @@ export declare class Path {
152
122
  */
153
123
  export declare function stringifyIfPath<T>(value: T | Path): T | string;
154
124
  export declare function mustNotHaveTrailingSlash(path: Path): void;
155
- export {};
@@ -1,6 +1,7 @@
1
1
  // src/Path.ts
2
2
  import {
3
3
  cp,
4
+ lstat,
4
5
  mkdir,
5
6
  mkdtemp,
6
7
  readdir,
@@ -8,6 +9,7 @@ import {
8
9
  rename,
9
10
  rm,
10
11
  stat,
12
+ symlink,
11
13
  writeFile
12
14
  } from "node:fs/promises";
13
15
  import { homedir, tmpdir } from "node:os";
@@ -263,6 +265,26 @@ var Path = class _Path {
263
265
  // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.
264
266
  readdir(this.#path, options)
265
267
  );
268
+ /** Returns the destination path. */
269
+ async symlink(target, type) {
270
+ const targetPath = new _Path(target);
271
+ await symlink(
272
+ this.path,
273
+ targetPath.path,
274
+ type
275
+ // 🤷
276
+ );
277
+ return targetPath;
278
+ }
279
+ // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.
280
+ stat = (...options) => stat(this.#path, ...options);
281
+ // I don't think `lstat` is a great name, but it does match the
282
+ // well-established canonical system call. So in this case we keep the
283
+ // awkward abbreviation.
284
+ lstat = (...options) => (
285
+ // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.
286
+ lstat(this.#path, ...options)
287
+ );
266
288
  static get homedir() {
267
289
  return new _Path(homedir());
268
290
  }
@@ -314,4 +336,4 @@ export {
314
336
  stringifyIfPath,
315
337
  mustNotHaveTrailingSlash
316
338
  };
317
- //# sourceMappingURL=chunk-KSCIGSNU.js.map
339
+ //# sourceMappingURL=chunk-DNNABIUU.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/Path.ts"],
4
+ "sourcesContent": ["import {\n cp,\n lstat,\n mkdir,\n mkdtemp,\n readdir,\n readFile,\n rename,\n rm,\n stat,\n symlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { basename, dirname, extname, join } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport {\n xdgCache,\n xdgConfig,\n xdgData,\n xdgRuntime,\n xdgState,\n} from \"xdg-basedir\";\nimport type {\n lstatType,\n readDirType,\n readFileType,\n statType,\n} from \"./modifiedNodeTypes\";\n\n// Note that (non-static) functions in this file are defined using `function(\u2026)\n// { \u2026 }` rather than arrow functions, specifically because we want `this` to\n// operate on the `Path` instance.\n\nexport class Path {\n // @ts-expect-error ts(2564): False positive. https://github.com/microsoft/TypeScript/issues/32194\n #path: string;\n /**\n * If `path` is a string starting with `file:///`, it will be parsed as a file URL.\n */\n constructor(path: string | URL | Path) {\n this.#setNormalizedPath(Path.#pathlikeToString(path));\n }\n\n /**\n * Similar to `new URL(path, base)`, but accepting and returning `Path` objects.\n * Note that `base` must be one of:\n *\n * - a valid second argument to `new URL(\u2026)`.\n * - a `Path` representing an absolute path.\n *\n */\n static resolve(path: string | URL | Path, base: string | URL | Path): Path {\n const baseURL = (() => {\n if (!(base instanceof Path)) {\n return base;\n }\n if (!base.isAbsolutePath()) {\n throw new Error(\n \"The `base` arg to `Path.resolve(\u2026)` must be an absolute path.\",\n );\n }\n return pathToFileURL(base.#path);\n })();\n return new Path(new URL(Path.#pathlikeToString(path), baseURL));\n }\n\n static #pathlikeToString(path: string | URL | Path): string {\n if (path instanceof Path) {\n return path.#path;\n }\n if (path instanceof URL) {\n return fileURLToPath(path);\n }\n if (typeof path === \"string\") {\n // TODO: allow turning off this heuristic?\n if (path.startsWith(\"file:///\")) {\n return fileURLToPath(path);\n }\n return path;\n }\n throw new Error(\"Invalid path\");\n }\n\n #setNormalizedPath(path: string): void {\n this.#path = join(path);\n }\n\n isAbsolutePath(): boolean {\n return this.#path.startsWith(\"/\");\n }\n\n toFileURL(): URL {\n if (!this.isAbsolutePath()) {\n throw new Error(\n \"Tried to convert to file URL when the path is not absolute.\",\n );\n }\n return pathToFileURL(this.#path);\n }\n\n /**\n * The `Path` can have a trailing slash, indicating that it represents a\n * directory. (If there is no trailing slash, it can represent either a file\n * or a directory.)\n *\n * Some operations will refuse to treat a directory path as a file path. This\n * function identifies such paths.\n */\n hasTrailingSlash(): boolean {\n // TODO: handle Windows semantically\n return this.#path.endsWith(\"/\");\n }\n\n /**\n * Same as `.toString()`, but more concise.\n */\n get path() {\n return this.#path;\n }\n\n toString(): string {\n return this.#path;\n }\n\n /** Constructs a new path by appending the given path segments.\n * This follows `node` semantics for absolute paths: leading slashes in the given descendant segments are ignored.\n */\n join(...segments: (string | Path)[]): Path {\n const segmentStrings = segments.map((segment) =>\n segment instanceof Path ? segment.path : segment,\n );\n return new Path(join(this.#path, ...segmentStrings));\n }\n\n extendBasename(suffix: string): Path {\n const joinedSuffix = join(suffix);\n if (joinedSuffix !== basename(joinedSuffix)) {\n throw new Error(\"Invalid suffix to extend file name.\");\n }\n // TODO: join basename and dirname instead?\n return new Path(this.#path + joinedSuffix);\n }\n\n get parent(): Path {\n return new Path(dirname(this.#path));\n }\n\n // Normally I'd stick with `node`'s name, but I think `.dirname` is a\n // particularly poor name. So we support `.dirname` for discovery but mark it\n // as deprecated, even if it will never be removed.\n /** @deprecated Alias for `.parent`. */\n get dirname(): Path {\n return this.parent;\n }\n\n get basename(): Path {\n return new Path(basename(this.#path));\n }\n\n get extension(): string {\n mustNotHaveTrailingSlash(this);\n return extname(this.#path);\n }\n\n // Normally I'd stick with `node`'s name, but I think `.extname` is a\n // particularly poor name. So we support `.extname` for discovery but mark it\n // as deprecated, even if it will never be removed.\n /** @deprecated Alias for `.extension`. */\n get extname(): string {\n return this.extension;\n }\n\n // TODO: find a neat way to dedup with the sync version?\n async exists(constraints?: {\n mustBe: \"file\" | \"directory\";\n }): Promise<boolean> {\n let stats: Awaited<ReturnType<typeof stat>>;\n try {\n stats = await stat(this.#path);\n // biome-ignore lint/suspicious/noExplicitAny: TypeScript limitation\n } catch (e: any) {\n if (e.code === \"ENOENT\") {\n return false;\n }\n throw e;\n }\n if (!constraints?.mustBe) {\n return true;\n }\n switch (constraints?.mustBe) {\n case \"file\": {\n mustNotHaveTrailingSlash(this);\n if (stats.isFile()) {\n return true;\n }\n throw new Error(`Path exists but is not a file: ${this.#path}`);\n }\n case \"directory\": {\n if (stats.isDirectory()) {\n return true;\n }\n throw new Error(`Path exists but is not a directory: ${this.#path}`);\n }\n default: {\n throw new Error(\"Invalid path type constraint\");\n }\n }\n }\n\n async existsAsFile(): Promise<boolean> {\n return this.exists({ mustBe: \"file\" });\n }\n\n async existsAsDir(): Promise<boolean> {\n return this.exists({ mustBe: \"directory\" });\n }\n\n // I don't think `mkdir` is a great name, but it does match the\n // well-established canonical commandline name. So in this case we keep the\n // awkward abbreviation.\n /** Defaults to `recursive: true`. */\n async mkdir(options?: Parameters<typeof mkdir>[1]): Promise<Path> {\n const optionsObject = (() => {\n if (typeof options === \"string\" || typeof options === \"number\") {\n return { mode: options };\n }\n return options ?? {};\n })();\n await mkdir(this.#path, { recursive: true, ...optionsObject });\n return this;\n }\n\n // TODO: check idempotency semantics when the destination exists and is a folder.\n /** Returns the destination path. */\n async cp(\n destination: string | URL | Path,\n options?: Parameters<typeof cp>[2],\n ): Promise<Path> {\n await cp(this.#path, new Path(destination).#path, options);\n return new Path(destination);\n }\n\n // TODO: check idempotency semantics when the destination exists and is a folder.\n async rename(destination: string | URL | Path): Promise<void> {\n await rename(this.#path, new Path(destination).#path);\n }\n\n /** Create a temporary dir inside the global temp dir for the current user. */\n static async makeTempDir(prefix?: string): Promise<Path> {\n return new Path(\n await mkdtemp(new Path(tmpdir()).join(prefix ?? \"js-temp-\").toString()),\n );\n }\n\n async rm(options?: Parameters<typeof rm>[1]): Promise<void> {\n await rm(this.#path, options);\n }\n\n /**\n * Equivalent to:\n *\n * .rm({ recursive: true, force: true, ...(options ?? {}) })\n *\n */\n async rm_rf(options?: Parameters<typeof rm>[1]): Promise<void> {\n await this.rm({ recursive: true, force: true, ...(options ?? {}) });\n }\n\n read: typeof readFileType = (options) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n readFile(this.#path, options as any) as any;\n\n async readText(): Promise<string> {\n return readFile(this.#path, \"utf-8\");\n }\n\n async readJSON<T>(): Promise<T> {\n return JSON.parse(await this.readText());\n }\n\n /** Creates intermediate directories if they do not exist.\n *\n * Returns the original `Path` (for chaining).\n */\n async write(\n data: Parameters<typeof writeFile>[1],\n options?: Parameters<typeof writeFile>[2],\n ): Promise<Path> {\n await this.parent.mkdir();\n await writeFile(this.#path, data, options);\n return this;\n }\n\n /**\n * If only `data` is provided, this is equivalent to:\n *\n * .write(JSON.stringify(data, null, \" \"));\n *\n * `replacer` and `space` can also be specified, making this equivalent to:\n *\n * .write(JSON.stringify(data, replacer, space));\n *\n * Returns the original `Path` (for chaining).\n */\n async writeJSON<T>(\n data: T,\n replacer: Parameters<typeof JSON.stringify>[1] = null,\n space: Parameters<typeof JSON.stringify>[2] = \" \",\n ): Promise<Path> {\n await this.write(JSON.stringify(data, replacer, space));\n return this;\n }\n\n // Normally we'd add a `@deprecated` alias named `.readdir`, but that would\n // differ only by capitalization of a single non-leading character. This can\n // be a bit confusing, especially when autocompleting. So for this function in\n // particular we don't include an alias.\n readDir: typeof readDirType = (options) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n readdir(this.#path, options as any) as any;\n\n /** Returns the destination path. */\n async symlink(\n target: string | URL | Path,\n type?: Parameters<typeof symlink>[2],\n ): Promise<Path> {\n const targetPath = new Path(target);\n await symlink(\n this.path,\n targetPath.path,\n type as Exclude<Parameters<typeof symlink>[2], undefined>, // \uD83E\uDD37\n );\n return targetPath;\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n stat: typeof statType = (...options) => stat(this.#path, ...options) as any;\n\n // I don't think `lstat` is a great name, but it does match the\n // well-established canonical system call. So in this case we keep the\n // awkward abbreviation.\n lstat: typeof lstatType = (...options) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n lstat(this.#path, ...options) as any;\n\n static get homedir(): Path {\n return new Path(homedir());\n }\n\n static xdg = {\n cache: new Path(xdgCache ?? Path.homedir.join(\".cache\")),\n config: new Path(xdgConfig ?? Path.homedir.join(\".config\")),\n data: new Path(xdgData ?? Path.homedir.join(\".local/share\")),\n state: new Path(xdgState ?? Path.homedir.join(\".local/state\")),\n /**\n * {@link Path.xdg.runtime} does not have a default value. Consider\n * {@link Path.xdg.runtimeWithStateFallback} if you need a fallback but do not have a particular fallback in mind.\n */\n runtime: xdgRuntime ? new Path(xdgRuntime) : undefined,\n runtimeWithStateFallback: xdgRuntime\n ? new Path(xdgRuntime)\n : new Path(xdgState ?? Path.homedir.join(\".local/state\")),\n };\n\n /** Chainable function to print the path. Prints the same as:\n *\n * if (args.length > 0) {\n * console.log(...args);\n * }\n * console.log(this.path);\n *\n */\n // biome-ignore lint/suspicious/noExplicitAny: This is the correct type, based on `console.log(\u2026)`.\n debugPrint(...args: any[]): Path {\n if (args.length > 0) {\n console.log(...args);\n }\n console.log(this.#path);\n return this;\n }\n}\n\n/**\n * This function is useful to serialize any `Path`s in a structure to pass on to\n * functions that do not know about the `Path` class, e.g.\n *\n * function process(args: (string | Path)[]) {\n * const argsAsStrings = args.map(stringifyIfPath);\n * }\n *\n */\nexport function stringifyIfPath<T>(value: T | Path): T | string {\n if (value instanceof Path) {\n return value.toString();\n }\n return value;\n}\n\nexport function mustNotHaveTrailingSlash(path: Path): void {\n if (path.hasTrailingSlash()) {\n throw new Error(\n \"Path ends with a slash, which cannot be treated as a file.\",\n );\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -2,7 +2,7 @@ import {
2
2
  Path,
3
3
  mustNotHaveTrailingSlash,
4
4
  stringifyIfPath
5
- } from "./chunks/chunk-KSCIGSNU.js";
5
+ } from "./chunks/chunk-DNNABIUU.js";
6
6
  export {
7
7
  Path,
8
8
  mustNotHaveTrailingSlash,
@@ -0,0 +1,53 @@
1
+ import type { Abortable } from "node:events";
2
+ import type { BigIntStats, Dirent, ObjectEncodingOptions, OpenMode, StatOptions, Stats } from "node:fs";
3
+ export declare function readDirType(options?: (ObjectEncodingOptions & {
4
+ withFileTypes?: false | undefined;
5
+ recursive?: boolean | undefined;
6
+ }) | BufferEncoding | null): Promise<string[]>;
7
+ export declare function readDirType(options: {
8
+ encoding: "buffer";
9
+ withFileTypes?: false | undefined;
10
+ recursive?: boolean | undefined;
11
+ } | "buffer"): Promise<Buffer[]>;
12
+ export declare function readDirType(options?: (ObjectEncodingOptions & {
13
+ withFileTypes?: false | undefined;
14
+ recursive?: boolean | undefined;
15
+ }) | BufferEncoding | null): Promise<string[] | Buffer[]>;
16
+ export declare function readDirType(options: ObjectEncodingOptions & {
17
+ withFileTypes: true;
18
+ recursive?: boolean | undefined;
19
+ }): Promise<Dirent[]>;
20
+ export declare function readDirType(options: {
21
+ encoding: "buffer";
22
+ withFileTypes: true;
23
+ recursive?: boolean | undefined;
24
+ }): Promise<Dirent<Buffer>[]>;
25
+ export declare function readFileType(options?: ({
26
+ encoding?: null | undefined;
27
+ flag?: OpenMode | undefined;
28
+ } & Abortable) | null): Promise<Buffer>;
29
+ export declare function readFileType(options: ({
30
+ encoding: BufferEncoding;
31
+ flag?: OpenMode | undefined;
32
+ } & Abortable) | BufferEncoding): Promise<string>;
33
+ export declare function readFileType(options?: (ObjectEncodingOptions & Abortable & {
34
+ flag?: OpenMode | undefined;
35
+ }) | BufferEncoding | null): Promise<string | Buffer>;
36
+ export declare function lstatType(opts?: StatOptions & {
37
+ bigint?: false | undefined;
38
+ }): Promise<Stats>;
39
+ export declare function lstatType(opts: StatOptions & {
40
+ bigint: true;
41
+ }): Promise<BigIntStats>;
42
+ export declare function lstatType(opts?: StatOptions): Promise<Stats | BigIntStats>;
43
+ /**
44
+ * @since v10.0.0
45
+ * @return Fulfills with the {fs.Stats} object for the given `path`.
46
+ */
47
+ export declare function statType(opts?: StatOptions & {
48
+ bigint?: false | undefined;
49
+ }): Promise<Stats>;
50
+ export declare function statType(opts: StatOptions & {
51
+ bigint: true;
52
+ }): Promise<BigIntStats>;
53
+ export declare function statType(opts?: StatOptions): Promise<Stats | BigIntStats>;
@@ -1,39 +1,6 @@
1
- import { cpSync, type Dirent, mkdirSync, type ObjectEncodingOptions, rmSync, writeFileSync } from "node:fs";
1
+ import { cpSync, mkdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
2
2
  import "./static";
3
- declare function readFileSyncType(options?: {
4
- encoding?: null | undefined;
5
- flag?: string | undefined;
6
- } | null): NonSharedBuffer;
7
- declare function readFileSyncType(options: {
8
- encoding: BufferEncoding;
9
- flag?: string | undefined;
10
- } | BufferEncoding): string;
11
- declare function readFileSyncType(options?: (ObjectEncodingOptions & {
12
- flag?: string | undefined;
13
- }) | BufferEncoding | null): string | NonSharedBuffer;
14
- declare function readDirSyncType(options?: {
15
- encoding: BufferEncoding | null;
16
- withFileTypes?: false | undefined;
17
- recursive?: boolean | undefined;
18
- } | BufferEncoding | null): string[];
19
- declare function readDirSyncType(options: {
20
- encoding: "buffer";
21
- withFileTypes?: false | undefined;
22
- recursive?: boolean | undefined;
23
- } | "buffer"): Buffer[];
24
- declare function readDirSyncType(options?: (ObjectEncodingOptions & {
25
- withFileTypes?: false | undefined;
26
- recursive?: boolean | undefined;
27
- }) | BufferEncoding | null): string[] | Buffer[];
28
- declare function readDirSyncType(options: ObjectEncodingOptions & {
29
- withFileTypes: true;
30
- recursive?: boolean | undefined;
31
- }): Dirent[];
32
- declare function readDirSyncType(options: {
33
- encoding: "buffer";
34
- withFileTypes: true;
35
- recursive?: boolean | undefined;
36
- }): Dirent<Buffer>[];
3
+ import type { lstatSyncType, readDirSyncType, readFileSyncType, statSyncType } from "./modifiedNodeTypes";
37
4
  declare module "../Path" {
38
5
  interface Path {
39
6
  existsSync(constraints?: {
@@ -52,6 +19,9 @@ declare module "../Path" {
52
19
  writeSync(data: Parameters<typeof writeFileSync>[1], options?: Parameters<typeof writeFileSync>[2] | undefined): Path;
53
20
  writeJSONSync<T>(data: T, replacer?: Parameters<typeof JSON.stringify>[1], space?: Parameters<typeof JSON.stringify>[2]): Path;
54
21
  readDirSync: typeof readDirSyncType;
22
+ /** Returns the destination path. */
23
+ symlinkSync(target: string | URL | Path, type?: Parameters<typeof symlinkSync>[2]): Path;
24
+ statSync: typeof statSyncType;
25
+ lstatSync: typeof lstatSyncType;
55
26
  }
56
27
  }
57
- export {};
@@ -1,17 +1,19 @@
1
1
  import {
2
2
  Path,
3
3
  mustNotHaveTrailingSlash
4
- } from "../chunks/chunk-KSCIGSNU.js";
4
+ } from "../chunks/chunk-DNNABIUU.js";
5
5
 
6
6
  // src/sync/index.ts
7
7
  import {
8
8
  cpSync,
9
+ lstatSync,
9
10
  mkdirSync,
10
11
  readdirSync,
11
12
  readFileSync,
12
13
  renameSync,
13
14
  rmSync,
14
15
  statSync,
16
+ symlinkSync,
15
17
  writeFileSync
16
18
  } from "node:fs";
17
19
 
@@ -106,4 +108,20 @@ Path.prototype.writeJSONSync = function(data, replacer = null, space = " ") {
106
108
  Path.prototype.readDirSync = function(options) {
107
109
  return readdirSync(this.path, options);
108
110
  };
111
+ Path.prototype.symlinkSync = function symlink(target, type) {
112
+ const targetPath = new Path(target);
113
+ symlinkSync(
114
+ this.path,
115
+ targetPath.path,
116
+ type
117
+ // 🤷
118
+ );
119
+ return targetPath;
120
+ };
121
+ Path.prototype.statSync = function(options) {
122
+ return statSync(this.path, options);
123
+ };
124
+ Path.prototype.lstatSync = function(options) {
125
+ return lstatSync(this.path, options);
126
+ };
109
127
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/sync/index.ts", "../../../../src/sync/static.ts"],
4
- "sourcesContent": ["import {\n cpSync,\n type Dirent,\n mkdirSync,\n type ObjectEncodingOptions,\n readdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { mustNotHaveTrailingSlash, Path } from \"../Path\";\nimport \"./static\";\n\n// Note that (non-static) functions in this file are defined using `function(\u2026)\n// { \u2026 }` rather than arrow functions, specifically because we want `this` to\n// operate on the `Path` instance.\n\ndeclare function readFileSyncType(\n options?: {\n encoding?: null | undefined;\n flag?: string | undefined;\n } | null,\n): NonSharedBuffer;\ndeclare function readFileSyncType(\n options:\n | {\n encoding: BufferEncoding;\n flag?: string | undefined;\n }\n | BufferEncoding,\n): string;\ndeclare function readFileSyncType(\n options?:\n | (ObjectEncodingOptions & {\n flag?: string | undefined;\n })\n | BufferEncoding\n | null,\n): string | NonSharedBuffer;\n\ndeclare function readDirSyncType(\n options?:\n | {\n encoding: BufferEncoding | null;\n withFileTypes?: false | undefined;\n recursive?: boolean | undefined;\n }\n | BufferEncoding\n | null,\n): string[];\ndeclare function readDirSyncType(\n options:\n | {\n encoding: \"buffer\";\n withFileTypes?: false | undefined;\n recursive?: boolean | undefined;\n }\n | \"buffer\",\n): Buffer[];\ndeclare function readDirSyncType(\n options?:\n | (ObjectEncodingOptions & {\n withFileTypes?: false | undefined;\n recursive?: boolean | undefined;\n })\n | BufferEncoding\n | null,\n): string[] | Buffer[];\ndeclare function readDirSyncType(\n options: ObjectEncodingOptions & {\n withFileTypes: true;\n recursive?: boolean | undefined;\n },\n): Dirent[];\ndeclare function readDirSyncType(options: {\n encoding: \"buffer\";\n withFileTypes: true;\n recursive?: boolean | undefined;\n}): Dirent<Buffer>[];\n\ndeclare module \"../Path\" {\n interface Path {\n existsSync(constraints?: { mustBe: \"file\" | \"directory\" }): boolean;\n existsAsFileSync(): boolean;\n existsAsDirSync(): boolean;\n\n mkdirSync(options?: Parameters<typeof mkdirSync>[1]): Path;\n cpSync(\n destination: string | URL | Path,\n options?: Parameters<typeof cpSync>[2],\n ): Path;\n renameSync(destination: string | URL | Path): void;\n\n rmSync(options?: Parameters<typeof rmSync>[1]): void;\n rm_rfSync(options?: Parameters<typeof rmSync>[1]): void;\n\n readSync: typeof readFileSyncType;\n readTextSync(): string;\n readJSONSync<T>(): T;\n\n writeSync(\n data: Parameters<typeof writeFileSync>[1],\n options?: Parameters<typeof writeFileSync>[2] | undefined,\n ): Path;\n writeJSONSync<T>(\n data: T,\n replacer?: Parameters<typeof JSON.stringify>[1],\n space?: Parameters<typeof JSON.stringify>[2],\n ): Path;\n\n readDirSync: typeof readDirSyncType;\n }\n}\n\n// TODO: find a neat way to dedup with the async version?\nPath.prototype.existsSync = function (constraints?: {\n mustBe: \"file\" | \"directory\";\n}): boolean {\n let stats: ReturnType<typeof statSync>;\n try {\n stats = statSync(this.path);\n // biome-ignore lint/suspicious/noExplicitAny: TypeScript limitation\n } catch (e: any) {\n if (e.code === \"ENOENT\") {\n return false;\n }\n throw e;\n }\n if (!constraints?.mustBe) {\n return true;\n }\n switch (constraints?.mustBe) {\n case \"file\": {\n mustNotHaveTrailingSlash(this);\n if (stats.isFile()) {\n return true;\n }\n throw new Error(`Path exists but is not a file: ${this.path}`);\n }\n case \"directory\": {\n if (stats.isDirectory()) {\n return true;\n }\n throw new Error(`Path exists but is not a directory: ${this.path}`);\n }\n default: {\n throw new Error(\"Invalid path type constraint\");\n }\n }\n};\n\nPath.prototype.existsAsFileSync = function (): boolean {\n return this.existsSync({ mustBe: \"file\" });\n};\n\nPath.prototype.existsAsDirSync = function (): boolean {\n return this.existsSync({ mustBe: \"directory\" });\n};\n\nPath.prototype.mkdirSync = function (\n options?: Parameters<typeof mkdirSync>[1],\n): Path {\n const optionsObject = (() => {\n if (typeof options === \"string\" || typeof options === \"number\") {\n return { mode: options };\n }\n return options ?? {};\n })();\n mkdirSync(this.path, { recursive: true, ...optionsObject });\n return this;\n};\n\nPath.prototype.cpSync = function (\n destination: string | URL | Path,\n options?: Parameters<typeof cpSync>[2],\n): Path {\n cpSync(this.path, new Path(destination).path, options);\n return new Path(destination);\n};\n\nPath.prototype.renameSync = function (destination: string | URL | Path): void {\n renameSync(this.path, new Path(destination).path);\n};\n\nPath.prototype.rmSync = function (\n options?: Parameters<typeof rmSync>[1],\n): void {\n rmSync(this.path, options);\n};\n\nPath.prototype.rm_rfSync = function (\n options?: Parameters<typeof rmSync>[1],\n): void {\n this.rmSync({ recursive: true, force: true, ...(options ?? {}) });\n};\n\nPath.prototype.readSync = function () {\n /** @ts-expect-error ts(2683) */\n return readFileSync(this.path);\n} as typeof readFileSyncType;\n\nPath.prototype.readTextSync = function (): string {\n return readFileSync(this.path, \"utf-8\");\n};\n\nPath.prototype.readJSONSync = function <T>(): T {\n return JSON.parse(this.readTextSync());\n};\n\nPath.prototype.writeSync = function (\n data: Parameters<typeof writeFileSync>[1],\n options?: Parameters<typeof writeFileSync>[2],\n): Path {\n this.parent.mkdirSync();\n writeFileSync(this.path, data, options);\n return this;\n};\n\nPath.prototype.writeJSONSync = function <T>(\n data: T,\n replacer: Parameters<typeof JSON.stringify>[1] = null,\n space: Parameters<typeof JSON.stringify>[2] = \" \",\n): Path {\n this.parent.mkdirSync();\n this.writeSync(JSON.stringify(data, replacer, space));\n return this;\n};\n\n/** @ts-expect-error ts(2322): Wrangle types */\nPath.prototype.readDirSync = function (options) {\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n return readdirSync(this.path, options as any);\n};\n", "import { mkdtempSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { Path } from \"../Path\";\n\ndeclare module \"../Path\" {\n namespace Path {\n export function makeTempDirSync(prefix?: string): Path;\n }\n}\n\nPath.makeTempDirSync = (prefix?: string): Path =>\n new Path(\n mkdtempSync(new Path(tmpdir()).join(prefix ?? \"js-temp-\").toString()),\n );\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n cpSync,\n lstatSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n symlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { mustNotHaveTrailingSlash, Path } from \"../Path\";\nimport \"./static\";\nimport type {\n lstatSyncType,\n readDirSyncType,\n readFileSyncType,\n statSyncType,\n} from \"./modifiedNodeTypes\";\n\n// Note that (non-static) functions in this file are defined using `function(\u2026)\n// { \u2026 }` rather than arrow functions, specifically because we want `this` to\n// operate on the `Path` instance.\n\ndeclare module \"../Path\" {\n interface Path {\n existsSync(constraints?: { mustBe: \"file\" | \"directory\" }): boolean;\n existsAsFileSync(): boolean;\n existsAsDirSync(): boolean;\n\n mkdirSync(options?: Parameters<typeof mkdirSync>[1]): Path;\n cpSync(\n destination: string | URL | Path,\n options?: Parameters<typeof cpSync>[2],\n ): Path;\n renameSync(destination: string | URL | Path): void;\n\n rmSync(options?: Parameters<typeof rmSync>[1]): void;\n rm_rfSync(options?: Parameters<typeof rmSync>[1]): void;\n\n readSync: typeof readFileSyncType;\n readTextSync(): string;\n readJSONSync<T>(): T;\n\n writeSync(\n data: Parameters<typeof writeFileSync>[1],\n options?: Parameters<typeof writeFileSync>[2] | undefined,\n ): Path;\n writeJSONSync<T>(\n data: T,\n replacer?: Parameters<typeof JSON.stringify>[1],\n space?: Parameters<typeof JSON.stringify>[2],\n ): Path;\n\n readDirSync: typeof readDirSyncType;\n\n /** Returns the destination path. */\n symlinkSync(\n target: string | URL | Path,\n type?: Parameters<typeof symlinkSync>[2],\n ): Path;\n\n statSync: typeof statSyncType;\n lstatSync: typeof lstatSyncType;\n }\n}\n\n// TODO: find a neat way to dedup with the async version?\nPath.prototype.existsSync = function (constraints?: {\n mustBe: \"file\" | \"directory\";\n}): boolean {\n let stats: ReturnType<typeof statSync>;\n try {\n stats = statSync(this.path);\n // biome-ignore lint/suspicious/noExplicitAny: TypeScript limitation\n } catch (e: any) {\n if (e.code === \"ENOENT\") {\n return false;\n }\n throw e;\n }\n if (!constraints?.mustBe) {\n return true;\n }\n switch (constraints?.mustBe) {\n case \"file\": {\n mustNotHaveTrailingSlash(this);\n if (stats.isFile()) {\n return true;\n }\n throw new Error(`Path exists but is not a file: ${this.path}`);\n }\n case \"directory\": {\n if (stats.isDirectory()) {\n return true;\n }\n throw new Error(`Path exists but is not a directory: ${this.path}`);\n }\n default: {\n throw new Error(\"Invalid path type constraint\");\n }\n }\n};\n\nPath.prototype.existsAsFileSync = function (): boolean {\n return this.existsSync({ mustBe: \"file\" });\n};\n\nPath.prototype.existsAsDirSync = function (): boolean {\n return this.existsSync({ mustBe: \"directory\" });\n};\n\nPath.prototype.mkdirSync = function (\n options?: Parameters<typeof mkdirSync>[1],\n): Path {\n const optionsObject = (() => {\n if (typeof options === \"string\" || typeof options === \"number\") {\n return { mode: options };\n }\n return options ?? {};\n })();\n mkdirSync(this.path, { recursive: true, ...optionsObject });\n return this;\n};\n\nPath.prototype.cpSync = function (\n destination: string | URL | Path,\n options?: Parameters<typeof cpSync>[2],\n): Path {\n cpSync(this.path, new Path(destination).path, options);\n return new Path(destination);\n};\n\nPath.prototype.renameSync = function (destination: string | URL | Path): void {\n renameSync(this.path, new Path(destination).path);\n};\n\nPath.prototype.rmSync = function (\n options?: Parameters<typeof rmSync>[1],\n): void {\n rmSync(this.path, options);\n};\n\nPath.prototype.rm_rfSync = function (\n options?: Parameters<typeof rmSync>[1],\n): void {\n this.rmSync({ recursive: true, force: true, ...(options ?? {}) });\n};\n\nPath.prototype.readSync = function () {\n /** @ts-expect-error ts(2683) */\n return readFileSync(this.path);\n} as typeof readFileSyncType;\n\nPath.prototype.readTextSync = function (): string {\n return readFileSync(this.path, \"utf-8\");\n};\n\nPath.prototype.readJSONSync = function <T>(): T {\n return JSON.parse(this.readTextSync());\n};\n\nPath.prototype.writeSync = function (\n data: Parameters<typeof writeFileSync>[1],\n options?: Parameters<typeof writeFileSync>[2],\n): Path {\n this.parent.mkdirSync();\n writeFileSync(this.path, data, options);\n return this;\n};\n\nPath.prototype.writeJSONSync = function <T>(\n data: T,\n replacer: Parameters<typeof JSON.stringify>[1] = null,\n space: Parameters<typeof JSON.stringify>[2] = \" \",\n): Path {\n this.parent.mkdirSync();\n this.writeSync(JSON.stringify(data, replacer, space));\n return this;\n};\n\n/** @ts-expect-error ts(2322): Wrangle types */\nPath.prototype.readDirSync = function (options) {\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n return readdirSync(this.path, options as any);\n};\n\nPath.prototype.symlinkSync = function symlink(\n target: string | URL | Path,\n type?: Parameters<typeof symlinkSync>[2],\n): Path {\n const targetPath = new Path(target);\n symlinkSync(\n this.path,\n targetPath.path,\n type as Exclude<Parameters<typeof symlinkSync>[2], undefined>, // \uD83E\uDD37\n );\n return targetPath;\n};\n\n/** @ts-expect-error ts(2322): Wrangle types */\nPath.prototype.statSync = function (\n options?: Parameters<typeof statSync>[1],\n): ReturnType<typeof statSync> {\n return statSync(this.path, options);\n};\n\n/** @ts-expect-error ts(2322): Wrangle types */\nPath.prototype.lstatSync = function (\n options?: Parameters<typeof lstatSync>[1],\n): ReturnType<typeof lstatSync> {\n return lstatSync(this.path, options);\n};\n", "import { mkdtempSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { Path } from \"../Path\";\n\ndeclare module \"../Path\" {\n namespace Path {\n export function makeTempDirSync(prefix?: string): Path;\n }\n}\n\nPath.makeTempDirSync = (prefix?: string): Path =>\n new Path(\n mkdtempSync(new Path(tmpdir()).join(prefix ?? \"js-temp-\").toString()),\n );\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,56 @@
1
+ import type { BigIntStats, Dirent, ObjectEncodingOptions, StatSyncOptions, Stats } from "node:fs";
2
+ export declare function readFileSyncType(options?: {
3
+ encoding?: null | undefined;
4
+ flag?: string | undefined;
5
+ } | null): NonSharedBuffer;
6
+ export declare function readFileSyncType(options: {
7
+ encoding: BufferEncoding;
8
+ flag?: string | undefined;
9
+ } | BufferEncoding): string;
10
+ export declare function readFileSyncType(options?: (ObjectEncodingOptions & {
11
+ flag?: string | undefined;
12
+ }) | BufferEncoding | null): string | NonSharedBuffer;
13
+ export declare function readDirSyncType(options?: {
14
+ encoding: BufferEncoding | null;
15
+ withFileTypes?: false | undefined;
16
+ recursive?: boolean | undefined;
17
+ } | BufferEncoding | null): string[];
18
+ export declare function readDirSyncType(options: {
19
+ encoding: "buffer";
20
+ withFileTypes?: false | undefined;
21
+ recursive?: boolean | undefined;
22
+ } | "buffer"): Buffer[];
23
+ export declare function readDirSyncType(options?: (ObjectEncodingOptions & {
24
+ withFileTypes?: false | undefined;
25
+ recursive?: boolean | undefined;
26
+ }) | BufferEncoding | null): string[] | Buffer[];
27
+ export declare function readDirSyncType(options: ObjectEncodingOptions & {
28
+ withFileTypes: true;
29
+ recursive?: boolean | undefined;
30
+ }): Dirent[];
31
+ export declare function readDirSyncType(options: {
32
+ encoding: "buffer";
33
+ withFileTypes: true;
34
+ recursive?: boolean | undefined;
35
+ }): Dirent<Buffer>[];
36
+ export declare function statSyncType(options?: undefined): Stats;
37
+ export declare function statSyncType(options?: StatSyncOptions & {
38
+ bigint?: false | undefined;
39
+ throwIfNoEntry: false;
40
+ }): Stats | undefined;
41
+ export declare function statSyncType(options: StatSyncOptions & {
42
+ bigint: true;
43
+ throwIfNoEntry: false;
44
+ }): BigIntStats | undefined;
45
+ export declare function statSyncType(options?: StatSyncOptions & {
46
+ bigint?: false | undefined;
47
+ }): Stats;
48
+ export declare function statSyncType(options: StatSyncOptions & {
49
+ bigint: true;
50
+ }): BigIntStats;
51
+ export declare function statSyncType(options: StatSyncOptions & {
52
+ bigint: boolean;
53
+ throwIfNoEntry?: false | undefined;
54
+ }): Stats | BigIntStats;
55
+ export declare function statSyncType(options?: StatSyncOptions): Stats | BigIntStats | undefined;
56
+ export declare const lstatSyncType: typeof statSyncType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "path-class",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "author": "Lucas Garron <code@garron.net>",
5
5
  "type": "module",
6
6
  "main": "./dist/lib/path-class/index.js",
package/src/Path.test.ts CHANGED
@@ -311,10 +311,43 @@ test(".readDir(…)", async () => {
311
311
  expect(new Set(contentsAsStrings)).toEqual(new Set(["file.txt", "dir"]));
312
312
 
313
313
  const contentsAsEntries = await dir.readDir({ withFileTypes: true });
314
- expect(contentsAsEntries.map((entry) => entry.name)).toEqual([
315
- "file.txt",
316
- "dir",
317
- ]);
314
+ expect(new Set(contentsAsEntries.map((entry) => entry.name))).toEqual(
315
+ new Set(["file.txt", "dir"]),
316
+ );
317
+ });
318
+
319
+ test(".symlink(…)", async () => {
320
+ const tempDir = await Path.makeTempDir();
321
+ const source = tempDir.join("foo.txt");
322
+ const target = tempDir.join("bar.txt");
323
+ await source.symlink(target);
324
+ expect(await target.existsAsFile()).toBe(false);
325
+ expect(() => target.readText()).toThrow(/ENOENT/);
326
+ await source.write("hello");
327
+ expect(await target.existsAsFile()).toBe(true);
328
+ expect(await target.readText()).toEqual("hello");
329
+ });
330
+
331
+ test(".stat(…)", async () => {
332
+ const file = (await Path.makeTempDir()).join("foo.txt");
333
+ await file.write("hello");
334
+
335
+ expect((await file.stat()).size).toEqual(5);
336
+ expect((await file.stat()).size).toBeTypeOf("number");
337
+ expect((await file.stat({ bigint: true })).size).toBeTypeOf("bigint");
338
+ });
339
+
340
+ test(".lstat(…)", async () => {
341
+ const tempDir = await Path.makeTempDir();
342
+ const source = tempDir.join("foo.txt");
343
+ const target = tempDir.join("bar.txt");
344
+ await source.symlink(target);
345
+ await source.write("hello");
346
+
347
+ expect((await source.lstat()).isSymbolicLink()).toBe(false);
348
+ expect((await target.lstat()).isSymbolicLink()).toBe(true);
349
+
350
+ expect(await target.readText()).toEqual("hello");
318
351
  });
319
352
 
320
353
  test(".homedir", async () => {
package/src/Path.ts CHANGED
@@ -1,7 +1,6 @@
1
- import type { Abortable } from "node:events";
2
- import type { Dirent, ObjectEncodingOptions, OpenMode } from "node:fs";
3
1
  import {
4
2
  cp,
3
+ lstat,
5
4
  mkdir,
6
5
  mkdtemp,
7
6
  readdir,
@@ -9,6 +8,7 @@ import {
9
8
  rename,
10
9
  rm,
11
10
  stat,
11
+ symlink,
12
12
  writeFile,
13
13
  } from "node:fs/promises";
14
14
  import { homedir, tmpdir } from "node:os";
@@ -21,80 +21,16 @@ import {
21
21
  xdgRuntime,
22
22
  xdgState,
23
23
  } from "xdg-basedir";
24
+ import type {
25
+ lstatType,
26
+ readDirType,
27
+ readFileType,
28
+ statType,
29
+ } from "./modifiedNodeTypes";
24
30
 
25
- // Modifying the type of `readdir()` from `node:fs/promises` to remove the
26
- // first parameter is difficult, if not impossible. So we give up and duplicate
27
- // the types manually. This ensures ergonomic types, such as an inferred return
28
- // type of `string[]` when `options` is not passed.
29
-
30
- declare function readDirType(
31
- options?:
32
- | (ObjectEncodingOptions & {
33
- withFileTypes?: false | undefined;
34
- recursive?: boolean | undefined;
35
- })
36
- | BufferEncoding
37
- | null,
38
- ): Promise<string[]>;
39
-
40
- declare function readDirType(
41
- options:
42
- | {
43
- encoding: "buffer";
44
- withFileTypes?: false | undefined;
45
- recursive?: boolean | undefined;
46
- }
47
- | "buffer",
48
- ): Promise<Buffer[]>;
49
-
50
- declare function readDirType(
51
- options?:
52
- | (ObjectEncodingOptions & {
53
- withFileTypes?: false | undefined;
54
- recursive?: boolean | undefined;
55
- })
56
- | BufferEncoding
57
- | null,
58
- ): Promise<string[] | Buffer[]>;
59
-
60
- declare function readDirType(
61
- options: ObjectEncodingOptions & {
62
- withFileTypes: true;
63
- recursive?: boolean | undefined;
64
- },
65
- ): Promise<Dirent[]>;
66
-
67
- declare function readDirType(options: {
68
- encoding: "buffer";
69
- withFileTypes: true;
70
- recursive?: boolean | undefined;
71
- }): Promise<Dirent<Buffer>[]>;
72
-
73
- declare function readFileType(
74
- options?:
75
- | ({
76
- encoding?: null | undefined;
77
- flag?: OpenMode | undefined;
78
- } & Abortable)
79
- | null,
80
- ): Promise<Buffer>;
81
- declare function readFileType(
82
- options:
83
- | ({
84
- encoding: BufferEncoding;
85
- flag?: OpenMode | undefined;
86
- } & Abortable)
87
- | BufferEncoding,
88
- ): Promise<string>;
89
- declare function readFileType(
90
- options?:
91
- | (ObjectEncodingOptions &
92
- Abortable & {
93
- flag?: OpenMode | undefined;
94
- })
95
- | BufferEncoding
96
- | null,
97
- ): Promise<string | Buffer>;
31
+ // Note that (non-static) functions in this file are defined using `function(…)
32
+ // { }` rather than arrow functions, specifically because we want `this` to
33
+ // operate on the `Path` instance.
98
34
 
99
35
  export class Path {
100
36
  // @ts-expect-error ts(2564): False positive. https://github.com/microsoft/TypeScript/issues/32194
@@ -384,6 +320,30 @@ export class Path {
384
320
  // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.
385
321
  readdir(this.#path, options as any) as any;
386
322
 
323
+ /** Returns the destination path. */
324
+ async symlink(
325
+ target: string | URL | Path,
326
+ type?: Parameters<typeof symlink>[2],
327
+ ): Promise<Path> {
328
+ const targetPath = new Path(target);
329
+ await symlink(
330
+ this.path,
331
+ targetPath.path,
332
+ type as Exclude<Parameters<typeof symlink>[2], undefined>, // 🤷
333
+ );
334
+ return targetPath;
335
+ }
336
+
337
+ // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.
338
+ stat: typeof statType = (...options) => stat(this.#path, ...options) as any;
339
+
340
+ // I don't think `lstat` is a great name, but it does match the
341
+ // well-established canonical system call. So in this case we keep the
342
+ // awkward abbreviation.
343
+ lstat: typeof lstatType = (...options) =>
344
+ // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.
345
+ lstat(this.#path, ...options) as any;
346
+
387
347
  static get homedir(): Path {
388
348
  return new Path(homedir());
389
349
  }
@@ -0,0 +1,116 @@
1
+ // Note: this file is `.ts` rather than `.d.ts` to ensure it ends up in the `tsc` output.
2
+
3
+ import type { Abortable } from "node:events";
4
+ import type {
5
+ BigIntStats,
6
+ Dirent,
7
+ ObjectEncodingOptions,
8
+ OpenMode,
9
+ StatOptions,
10
+ Stats,
11
+ } from "node:fs";
12
+
13
+ // Modifying the type of `readdir(…)` from `node:fs/promises` to remove the
14
+ // first parameter is difficult, if not impossible. So we give up and duplicate
15
+ // the types manually. This ensures ergonomic types, such as an inferred return
16
+ // type of `string[]` when `options` is not passed.
17
+
18
+ export declare function readDirType(
19
+ options?:
20
+ | (ObjectEncodingOptions & {
21
+ withFileTypes?: false | undefined;
22
+ recursive?: boolean | undefined;
23
+ })
24
+ | BufferEncoding
25
+ | null,
26
+ ): Promise<string[]>;
27
+
28
+ export declare function readDirType(
29
+ options:
30
+ | {
31
+ encoding: "buffer";
32
+ withFileTypes?: false | undefined;
33
+ recursive?: boolean | undefined;
34
+ }
35
+ | "buffer",
36
+ ): Promise<Buffer[]>;
37
+
38
+ export declare function readDirType(
39
+ options?:
40
+ | (ObjectEncodingOptions & {
41
+ withFileTypes?: false | undefined;
42
+ recursive?: boolean | undefined;
43
+ })
44
+ | BufferEncoding
45
+ | null,
46
+ ): Promise<string[] | Buffer[]>;
47
+
48
+ export declare function readDirType(
49
+ options: ObjectEncodingOptions & {
50
+ withFileTypes: true;
51
+ recursive?: boolean | undefined;
52
+ },
53
+ ): Promise<Dirent[]>;
54
+
55
+ export declare function readDirType(options: {
56
+ encoding: "buffer";
57
+ withFileTypes: true;
58
+ recursive?: boolean | undefined;
59
+ }): Promise<Dirent<Buffer>[]>;
60
+
61
+ export declare function readFileType(
62
+ options?:
63
+ | ({
64
+ encoding?: null | undefined;
65
+ flag?: OpenMode | undefined;
66
+ } & Abortable)
67
+ | null,
68
+ ): Promise<Buffer>;
69
+ export declare function readFileType(
70
+ options:
71
+ | ({
72
+ encoding: BufferEncoding;
73
+ flag?: OpenMode | undefined;
74
+ } & Abortable)
75
+ | BufferEncoding,
76
+ ): Promise<string>;
77
+ export declare function readFileType(
78
+ options?:
79
+ | (ObjectEncodingOptions &
80
+ Abortable & {
81
+ flag?: OpenMode | undefined;
82
+ })
83
+ | BufferEncoding
84
+ | null,
85
+ ): Promise<string | Buffer>;
86
+
87
+ export declare function lstatType(
88
+ opts?: StatOptions & {
89
+ bigint?: false | undefined;
90
+ },
91
+ ): Promise<Stats>;
92
+ export declare function lstatType(
93
+ opts: StatOptions & {
94
+ bigint: true;
95
+ },
96
+ ): Promise<BigIntStats>;
97
+ export declare function lstatType(
98
+ opts?: StatOptions,
99
+ ): Promise<Stats | BigIntStats>;
100
+ /**
101
+ * @since v10.0.0
102
+ * @return Fulfills with the {fs.Stats} object for the given `path`.
103
+ */
104
+ export declare function statType(
105
+ opts?: StatOptions & {
106
+ bigint?: false | undefined;
107
+ },
108
+ ): Promise<Stats>;
109
+ export declare function statType(
110
+ opts: StatOptions & {
111
+ bigint: true;
112
+ },
113
+ ): Promise<BigIntStats>;
114
+ export declare function statType(
115
+ opts?: StatOptions,
116
+ ): Promise<Stats | BigIntStats>;
package/src/sync/index.ts CHANGED
@@ -1,85 +1,28 @@
1
1
  import {
2
2
  cpSync,
3
- type Dirent,
3
+ lstatSync,
4
4
  mkdirSync,
5
- type ObjectEncodingOptions,
6
5
  readdirSync,
7
6
  readFileSync,
8
7
  renameSync,
9
8
  rmSync,
10
9
  statSync,
10
+ symlinkSync,
11
11
  writeFileSync,
12
12
  } from "node:fs";
13
13
  import { mustNotHaveTrailingSlash, Path } from "../Path";
14
14
  import "./static";
15
+ import type {
16
+ lstatSyncType,
17
+ readDirSyncType,
18
+ readFileSyncType,
19
+ statSyncType,
20
+ } from "./modifiedNodeTypes";
15
21
 
16
22
  // Note that (non-static) functions in this file are defined using `function(…)
17
23
  // { … }` rather than arrow functions, specifically because we want `this` to
18
24
  // operate on the `Path` instance.
19
25
 
20
- declare function readFileSyncType(
21
- options?: {
22
- encoding?: null | undefined;
23
- flag?: string | undefined;
24
- } | null,
25
- ): NonSharedBuffer;
26
- declare function readFileSyncType(
27
- options:
28
- | {
29
- encoding: BufferEncoding;
30
- flag?: string | undefined;
31
- }
32
- | BufferEncoding,
33
- ): string;
34
- declare function readFileSyncType(
35
- options?:
36
- | (ObjectEncodingOptions & {
37
- flag?: string | undefined;
38
- })
39
- | BufferEncoding
40
- | null,
41
- ): string | NonSharedBuffer;
42
-
43
- declare function readDirSyncType(
44
- options?:
45
- | {
46
- encoding: BufferEncoding | null;
47
- withFileTypes?: false | undefined;
48
- recursive?: boolean | undefined;
49
- }
50
- | BufferEncoding
51
- | null,
52
- ): string[];
53
- declare function readDirSyncType(
54
- options:
55
- | {
56
- encoding: "buffer";
57
- withFileTypes?: false | undefined;
58
- recursive?: boolean | undefined;
59
- }
60
- | "buffer",
61
- ): Buffer[];
62
- declare function readDirSyncType(
63
- options?:
64
- | (ObjectEncodingOptions & {
65
- withFileTypes?: false | undefined;
66
- recursive?: boolean | undefined;
67
- })
68
- | BufferEncoding
69
- | null,
70
- ): string[] | Buffer[];
71
- declare function readDirSyncType(
72
- options: ObjectEncodingOptions & {
73
- withFileTypes: true;
74
- recursive?: boolean | undefined;
75
- },
76
- ): Dirent[];
77
- declare function readDirSyncType(options: {
78
- encoding: "buffer";
79
- withFileTypes: true;
80
- recursive?: boolean | undefined;
81
- }): Dirent<Buffer>[];
82
-
83
26
  declare module "../Path" {
84
27
  interface Path {
85
28
  existsSync(constraints?: { mustBe: "file" | "directory" }): boolean;
@@ -111,6 +54,15 @@ declare module "../Path" {
111
54
  ): Path;
112
55
 
113
56
  readDirSync: typeof readDirSyncType;
57
+
58
+ /** Returns the destination path. */
59
+ symlinkSync(
60
+ target: string | URL | Path,
61
+ type?: Parameters<typeof symlinkSync>[2],
62
+ ): Path;
63
+
64
+ statSync: typeof statSyncType;
65
+ lstatSync: typeof lstatSyncType;
114
66
  }
115
67
  }
116
68
 
@@ -233,3 +185,30 @@ Path.prototype.readDirSync = function (options) {
233
185
  // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.
234
186
  return readdirSync(this.path, options as any);
235
187
  };
188
+
189
+ Path.prototype.symlinkSync = function symlink(
190
+ target: string | URL | Path,
191
+ type?: Parameters<typeof symlinkSync>[2],
192
+ ): Path {
193
+ const targetPath = new Path(target);
194
+ symlinkSync(
195
+ this.path,
196
+ targetPath.path,
197
+ type as Exclude<Parameters<typeof symlinkSync>[2], undefined>, // 🤷
198
+ );
199
+ return targetPath;
200
+ };
201
+
202
+ /** @ts-expect-error ts(2322): Wrangle types */
203
+ Path.prototype.statSync = function (
204
+ options?: Parameters<typeof statSync>[1],
205
+ ): ReturnType<typeof statSync> {
206
+ return statSync(this.path, options);
207
+ };
208
+
209
+ /** @ts-expect-error ts(2322): Wrangle types */
210
+ Path.prototype.lstatSync = function (
211
+ options?: Parameters<typeof lstatSync>[1],
212
+ ): ReturnType<typeof lstatSync> {
213
+ return lstatSync(this.path, options);
214
+ };
@@ -0,0 +1,107 @@
1
+ // Note: this file is `.ts` rather than `.d.ts` to ensure it ends up in the `tsc` output.
2
+
3
+ import type {
4
+ BigIntStats,
5
+ Dirent,
6
+ ObjectEncodingOptions,
7
+ StatSyncOptions,
8
+ Stats,
9
+ } from "node:fs";
10
+
11
+ export declare function readFileSyncType(
12
+ options?: {
13
+ encoding?: null | undefined;
14
+ flag?: string | undefined;
15
+ } | null,
16
+ ): NonSharedBuffer;
17
+ export declare function readFileSyncType(
18
+ options:
19
+ | {
20
+ encoding: BufferEncoding;
21
+ flag?: string | undefined;
22
+ }
23
+ | BufferEncoding,
24
+ ): string;
25
+ export declare function readFileSyncType(
26
+ options?:
27
+ | (ObjectEncodingOptions & {
28
+ flag?: string | undefined;
29
+ })
30
+ | BufferEncoding
31
+ | null,
32
+ ): string | NonSharedBuffer;
33
+
34
+ export declare function readDirSyncType(
35
+ options?:
36
+ | {
37
+ encoding: BufferEncoding | null;
38
+ withFileTypes?: false | undefined;
39
+ recursive?: boolean | undefined;
40
+ }
41
+ | BufferEncoding
42
+ | null,
43
+ ): string[];
44
+ export declare function readDirSyncType(
45
+ options:
46
+ | {
47
+ encoding: "buffer";
48
+ withFileTypes?: false | undefined;
49
+ recursive?: boolean | undefined;
50
+ }
51
+ | "buffer",
52
+ ): Buffer[];
53
+ export declare function readDirSyncType(
54
+ options?:
55
+ | (ObjectEncodingOptions & {
56
+ withFileTypes?: false | undefined;
57
+ recursive?: boolean | undefined;
58
+ })
59
+ | BufferEncoding
60
+ | null,
61
+ ): string[] | Buffer[];
62
+ export declare function readDirSyncType(
63
+ options: ObjectEncodingOptions & {
64
+ withFileTypes: true;
65
+ recursive?: boolean | undefined;
66
+ },
67
+ ): Dirent[];
68
+ export declare function readDirSyncType(options: {
69
+ encoding: "buffer";
70
+ withFileTypes: true;
71
+ recursive?: boolean | undefined;
72
+ }): Dirent<Buffer>[];
73
+
74
+ export declare function statSyncType(options?: undefined): Stats;
75
+ export declare function statSyncType(
76
+ options?: StatSyncOptions & {
77
+ bigint?: false | undefined;
78
+ throwIfNoEntry: false;
79
+ },
80
+ ): Stats | undefined;
81
+ export declare function statSyncType(
82
+ options: StatSyncOptions & {
83
+ bigint: true;
84
+ throwIfNoEntry: false;
85
+ },
86
+ ): BigIntStats | undefined;
87
+ export declare function statSyncType(
88
+ options?: StatSyncOptions & {
89
+ bigint?: false | undefined;
90
+ },
91
+ ): Stats;
92
+ export declare function statSyncType(
93
+ options: StatSyncOptions & {
94
+ bigint: true;
95
+ },
96
+ ): BigIntStats;
97
+ export declare function statSyncType(
98
+ options: StatSyncOptions & {
99
+ bigint: boolean;
100
+ throwIfNoEntry?: false | undefined;
101
+ },
102
+ ): Stats | BigIntStats;
103
+ export declare function statSyncType(
104
+ options?: StatSyncOptions,
105
+ ): Stats | BigIntStats | undefined;
106
+
107
+ export declare const lstatSyncType: typeof statSyncType;
@@ -184,8 +184,41 @@ test(".readDirSync(…)", () => {
184
184
  expect(new Set(contentsAsStrings)).toEqual(new Set(["file.txt", "dir"]));
185
185
 
186
186
  const contentsAsEntries = dir.readDirSync({ withFileTypes: true });
187
- expect(contentsAsEntries.map((entry) => entry.name)).toEqual([
188
- "file.txt",
189
- "dir",
190
- ]);
187
+ expect(new Set(contentsAsEntries.map((entry) => entry.name))).toEqual(
188
+ new Set(["file.txt", "dir"]),
189
+ );
190
+ });
191
+
192
+ test(".symlinkSync(…)", () => {
193
+ const tempDir = Path.makeTempDirSync();
194
+ const source = tempDir.join("foo.txt");
195
+ const target = tempDir.join("bar.txt");
196
+ source.symlinkSync(target);
197
+ expect(target.existsAsFileSync()).toBe(false);
198
+ expect(() => target.readText()).toThrow(/ENOENT/);
199
+ source.writeSync("hello");
200
+ expect(target.existsAsFileSync()).toBe(true);
201
+ expect(target.readTextSync()).toEqual("hello");
202
+ });
203
+
204
+ test(".statSync(…)", () => {
205
+ const file = Path.makeTempDirSync().join("foo.txt");
206
+ file.writeSync("hello");
207
+
208
+ expect(file.statSync()?.size).toEqual(5);
209
+ expect(file.statSync()?.size).toBeTypeOf("number");
210
+ expect(file.statSync({ bigint: true })?.size).toBeTypeOf("bigint");
211
+ });
212
+
213
+ test(".lstatSync(…)", () => {
214
+ const tempDir = Path.makeTempDirSync();
215
+ const source = tempDir.join("foo.txt");
216
+ const target = tempDir.join("bar.txt");
217
+ source.symlinkSync(target);
218
+ source.writeSync("hello");
219
+
220
+ expect(source.lstatSync()?.isSymbolicLink()).toBe(false);
221
+ expect(target.lstatSync()?.isSymbolicLink()).toBe(true);
222
+
223
+ expect(target.readTextSync()).toEqual("hello");
191
224
  });
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/Path.ts"],
4
- "sourcesContent": ["import type { Abortable } from \"node:events\";\nimport type { Dirent, ObjectEncodingOptions, OpenMode } from \"node:fs\";\nimport {\n cp,\n mkdir,\n mkdtemp,\n readdir,\n readFile,\n rename,\n rm,\n stat,\n writeFile,\n} from \"node:fs/promises\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { basename, dirname, extname, join } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport {\n xdgCache,\n xdgConfig,\n xdgData,\n xdgRuntime,\n xdgState,\n} from \"xdg-basedir\";\n\n// Modifying the type of `readdir(\u2026)` from `node:fs/promises` to remove the\n// first parameter is difficult, if not impossible. So we give up and duplicate\n// the types manually. This ensures ergonomic types, such as an inferred return\n// type of `string[]` when `options` is not passed.\n\ndeclare function readDirType(\n options?:\n | (ObjectEncodingOptions & {\n withFileTypes?: false | undefined;\n recursive?: boolean | undefined;\n })\n | BufferEncoding\n | null,\n): Promise<string[]>;\n\ndeclare function readDirType(\n options:\n | {\n encoding: \"buffer\";\n withFileTypes?: false | undefined;\n recursive?: boolean | undefined;\n }\n | \"buffer\",\n): Promise<Buffer[]>;\n\ndeclare function readDirType(\n options?:\n | (ObjectEncodingOptions & {\n withFileTypes?: false | undefined;\n recursive?: boolean | undefined;\n })\n | BufferEncoding\n | null,\n): Promise<string[] | Buffer[]>;\n\ndeclare function readDirType(\n options: ObjectEncodingOptions & {\n withFileTypes: true;\n recursive?: boolean | undefined;\n },\n): Promise<Dirent[]>;\n\ndeclare function readDirType(options: {\n encoding: \"buffer\";\n withFileTypes: true;\n recursive?: boolean | undefined;\n}): Promise<Dirent<Buffer>[]>;\n\ndeclare function readFileType(\n options?:\n | ({\n encoding?: null | undefined;\n flag?: OpenMode | undefined;\n } & Abortable)\n | null,\n): Promise<Buffer>;\ndeclare function readFileType(\n options:\n | ({\n encoding: BufferEncoding;\n flag?: OpenMode | undefined;\n } & Abortable)\n | BufferEncoding,\n): Promise<string>;\ndeclare function readFileType(\n options?:\n | (ObjectEncodingOptions &\n Abortable & {\n flag?: OpenMode | undefined;\n })\n | BufferEncoding\n | null,\n): Promise<string | Buffer>;\n\nexport class Path {\n // @ts-expect-error ts(2564): False positive. https://github.com/microsoft/TypeScript/issues/32194\n #path: string;\n /**\n * If `path` is a string starting with `file:///`, it will be parsed as a file URL.\n */\n constructor(path: string | URL | Path) {\n this.#setNormalizedPath(Path.#pathlikeToString(path));\n }\n\n /**\n * Similar to `new URL(path, base)`, but accepting and returning `Path` objects.\n * Note that `base` must be one of:\n *\n * - a valid second argument to `new URL(\u2026)`.\n * - a `Path` representing an absolute path.\n *\n */\n static resolve(path: string | URL | Path, base: string | URL | Path): Path {\n const baseURL = (() => {\n if (!(base instanceof Path)) {\n return base;\n }\n if (!base.isAbsolutePath()) {\n throw new Error(\n \"The `base` arg to `Path.resolve(\u2026)` must be an absolute path.\",\n );\n }\n return pathToFileURL(base.#path);\n })();\n return new Path(new URL(Path.#pathlikeToString(path), baseURL));\n }\n\n static #pathlikeToString(path: string | URL | Path): string {\n if (path instanceof Path) {\n return path.#path;\n }\n if (path instanceof URL) {\n return fileURLToPath(path);\n }\n if (typeof path === \"string\") {\n // TODO: allow turning off this heuristic?\n if (path.startsWith(\"file:///\")) {\n return fileURLToPath(path);\n }\n return path;\n }\n throw new Error(\"Invalid path\");\n }\n\n #setNormalizedPath(path: string): void {\n this.#path = join(path);\n }\n\n isAbsolutePath(): boolean {\n return this.#path.startsWith(\"/\");\n }\n\n toFileURL(): URL {\n if (!this.isAbsolutePath()) {\n throw new Error(\n \"Tried to convert to file URL when the path is not absolute.\",\n );\n }\n return pathToFileURL(this.#path);\n }\n\n /**\n * The `Path` can have a trailing slash, indicating that it represents a\n * directory. (If there is no trailing slash, it can represent either a file\n * or a directory.)\n *\n * Some operations will refuse to treat a directory path as a file path. This\n * function identifies such paths.\n */\n hasTrailingSlash(): boolean {\n // TODO: handle Windows semantically\n return this.#path.endsWith(\"/\");\n }\n\n /**\n * Same as `.toString()`, but more concise.\n */\n get path() {\n return this.#path;\n }\n\n toString(): string {\n return this.#path;\n }\n\n /** Constructs a new path by appending the given path segments.\n * This follows `node` semantics for absolute paths: leading slashes in the given descendant segments are ignored.\n */\n join(...segments: (string | Path)[]): Path {\n const segmentStrings = segments.map((segment) =>\n segment instanceof Path ? segment.path : segment,\n );\n return new Path(join(this.#path, ...segmentStrings));\n }\n\n extendBasename(suffix: string): Path {\n const joinedSuffix = join(suffix);\n if (joinedSuffix !== basename(joinedSuffix)) {\n throw new Error(\"Invalid suffix to extend file name.\");\n }\n // TODO: join basename and dirname instead?\n return new Path(this.#path + joinedSuffix);\n }\n\n get parent(): Path {\n return new Path(dirname(this.#path));\n }\n\n // Normally I'd stick with `node`'s name, but I think `.dirname` is a\n // particularly poor name. So we support `.dirname` for discovery but mark it\n // as deprecated, even if it will never be removed.\n /** @deprecated Alias for `.parent`. */\n get dirname(): Path {\n return this.parent;\n }\n\n get basename(): Path {\n return new Path(basename(this.#path));\n }\n\n get extension(): string {\n mustNotHaveTrailingSlash(this);\n return extname(this.#path);\n }\n\n // Normally I'd stick with `node`'s name, but I think `.extname` is a\n // particularly poor name. So we support `.extname` for discovery but mark it\n // as deprecated, even if it will never be removed.\n /** @deprecated Alias for `.extension`. */\n get extname(): string {\n return this.extension;\n }\n\n // TODO: find a neat way to dedup with the sync version?\n async exists(constraints?: {\n mustBe: \"file\" | \"directory\";\n }): Promise<boolean> {\n let stats: Awaited<ReturnType<typeof stat>>;\n try {\n stats = await stat(this.#path);\n // biome-ignore lint/suspicious/noExplicitAny: TypeScript limitation\n } catch (e: any) {\n if (e.code === \"ENOENT\") {\n return false;\n }\n throw e;\n }\n if (!constraints?.mustBe) {\n return true;\n }\n switch (constraints?.mustBe) {\n case \"file\": {\n mustNotHaveTrailingSlash(this);\n if (stats.isFile()) {\n return true;\n }\n throw new Error(`Path exists but is not a file: ${this.#path}`);\n }\n case \"directory\": {\n if (stats.isDirectory()) {\n return true;\n }\n throw new Error(`Path exists but is not a directory: ${this.#path}`);\n }\n default: {\n throw new Error(\"Invalid path type constraint\");\n }\n }\n }\n\n async existsAsFile(): Promise<boolean> {\n return this.exists({ mustBe: \"file\" });\n }\n\n async existsAsDir(): Promise<boolean> {\n return this.exists({ mustBe: \"directory\" });\n }\n\n // I don't think `mkdir` is a great name, but it does match the\n // well-established canonical commandline name. So in this case we keep the\n // awkward abbreviation.\n /** Defaults to `recursive: true`. */\n async mkdir(options?: Parameters<typeof mkdir>[1]): Promise<Path> {\n const optionsObject = (() => {\n if (typeof options === \"string\" || typeof options === \"number\") {\n return { mode: options };\n }\n return options ?? {};\n })();\n await mkdir(this.#path, { recursive: true, ...optionsObject });\n return this;\n }\n\n // TODO: check idempotency semantics when the destination exists and is a folder.\n /** Returns the destination path. */\n async cp(\n destination: string | URL | Path,\n options?: Parameters<typeof cp>[2],\n ): Promise<Path> {\n await cp(this.#path, new Path(destination).#path, options);\n return new Path(destination);\n }\n\n // TODO: check idempotency semantics when the destination exists and is a folder.\n async rename(destination: string | URL | Path): Promise<void> {\n await rename(this.#path, new Path(destination).#path);\n }\n\n /** Create a temporary dir inside the global temp dir for the current user. */\n static async makeTempDir(prefix?: string): Promise<Path> {\n return new Path(\n await mkdtemp(new Path(tmpdir()).join(prefix ?? \"js-temp-\").toString()),\n );\n }\n\n async rm(options?: Parameters<typeof rm>[1]): Promise<void> {\n await rm(this.#path, options);\n }\n\n /**\n * Equivalent to:\n *\n * .rm({ recursive: true, force: true, ...(options ?? {}) })\n *\n */\n async rm_rf(options?: Parameters<typeof rm>[1]): Promise<void> {\n await this.rm({ recursive: true, force: true, ...(options ?? {}) });\n }\n\n read: typeof readFileType = (options) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n readFile(this.#path, options as any) as any;\n\n async readText(): Promise<string> {\n return readFile(this.#path, \"utf-8\");\n }\n\n async readJSON<T>(): Promise<T> {\n return JSON.parse(await this.readText());\n }\n\n /** Creates intermediate directories if they do not exist.\n *\n * Returns the original `Path` (for chaining).\n */\n async write(\n data: Parameters<typeof writeFile>[1],\n options?: Parameters<typeof writeFile>[2],\n ): Promise<Path> {\n await this.parent.mkdir();\n await writeFile(this.#path, data, options);\n return this;\n }\n\n /**\n * If only `data` is provided, this is equivalent to:\n *\n * .write(JSON.stringify(data, null, \" \"));\n *\n * `replacer` and `space` can also be specified, making this equivalent to:\n *\n * .write(JSON.stringify(data, replacer, space));\n *\n * Returns the original `Path` (for chaining).\n */\n async writeJSON<T>(\n data: T,\n replacer: Parameters<typeof JSON.stringify>[1] = null,\n space: Parameters<typeof JSON.stringify>[2] = \" \",\n ): Promise<Path> {\n await this.write(JSON.stringify(data, replacer, space));\n return this;\n }\n\n // Normally we'd add a `@deprecated` alias named `.readdir`, but that would\n // differ only by capitalization of a single non-leading character. This can\n // be a bit confusing, especially when autocompleting. So for this function in\n // particular we don't include an alias.\n readDir: typeof readDirType = (options) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n readdir(this.#path, options as any) as any;\n\n static get homedir(): Path {\n return new Path(homedir());\n }\n\n static xdg = {\n cache: new Path(xdgCache ?? Path.homedir.join(\".cache\")),\n config: new Path(xdgConfig ?? Path.homedir.join(\".config\")),\n data: new Path(xdgData ?? Path.homedir.join(\".local/share\")),\n state: new Path(xdgState ?? Path.homedir.join(\".local/state\")),\n /**\n * {@link Path.xdg.runtime} does not have a default value. Consider\n * {@link Path.xdg.runtimeWithStateFallback} if you need a fallback but do not have a particular fallback in mind.\n */\n runtime: xdgRuntime ? new Path(xdgRuntime) : undefined,\n runtimeWithStateFallback: xdgRuntime\n ? new Path(xdgRuntime)\n : new Path(xdgState ?? Path.homedir.join(\".local/state\")),\n };\n\n /** Chainable function to print the path. Prints the same as:\n *\n * if (args.length > 0) {\n * console.log(...args);\n * }\n * console.log(this.path);\n *\n */\n // biome-ignore lint/suspicious/noExplicitAny: This is the correct type, based on `console.log(\u2026)`.\n debugPrint(...args: any[]): Path {\n if (args.length > 0) {\n console.log(...args);\n }\n console.log(this.#path);\n return this;\n }\n}\n\n/**\n * This function is useful to serialize any `Path`s in a structure to pass on to\n * functions that do not know about the `Path` class, e.g.\n *\n * function process(args: (string | Path)[]) {\n * const argsAsStrings = args.map(stringifyIfPath);\n * }\n *\n */\nexport function stringifyIfPath<T>(value: T | Path): T | string {\n if (value instanceof Path) {\n return value.toString();\n }\n return value;\n}\n\nexport function mustNotHaveTrailingSlash(path: Path): void {\n if (path.hasTrailingSlash()) {\n throw new Error(\n \"Path ends with a slash, which cannot be treated as a file.\",\n );\n }\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }