path-class 0.11.0 → 0.11.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.
- package/dist/lib/path-class/Path.d.ts +9 -0
- package/dist/lib/path-class/chunks/{chunk-HPGQLKA5.js → chunk-QM7EHUFF.js} +15 -3
- package/dist/lib/path-class/chunks/chunk-QM7EHUFF.js.map +7 -0
- package/dist/lib/path-class/index.js +1 -1
- package/dist/lib/path-class/sync/index.js +2 -2
- package/dist/lib/path-class/sync/index.js.map +2 -2
- package/package.json +1 -1
- package/src/Path.test.ts +64 -49
- package/src/Path.ts +15 -6
- package/src/sync/PathSync.test.ts +32 -26
- package/src/sync/PathSync.ts +1 -5
- package/dist/lib/path-class/chunks/chunk-HPGQLKA5.js.map +0 -7
|
@@ -45,6 +45,15 @@ export declare class Path {
|
|
|
45
45
|
*/
|
|
46
46
|
get path(): string;
|
|
47
47
|
toString(): string;
|
|
48
|
+
/**
|
|
49
|
+
* Format this with the escape codes for printing to the shell in bold blue.
|
|
50
|
+
*
|
|
51
|
+
* Example usage:
|
|
52
|
+
*
|
|
53
|
+
* console.log(`Processing: ${path.blue}`)
|
|
54
|
+
*
|
|
55
|
+
*/
|
|
56
|
+
get blue(): string;
|
|
48
57
|
/** Constructs a new path by appending the given path segments.
|
|
49
58
|
* This follows `node` semantics for absolute paths: leading slashes in the given descendant segments are ignored.
|
|
50
59
|
*/
|
|
@@ -179,6 +179,18 @@ var Path = class _Path {
|
|
|
179
179
|
toString() {
|
|
180
180
|
return this.#path;
|
|
181
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Format this with the escape codes for printing to the shell in bold blue.
|
|
184
|
+
*
|
|
185
|
+
* Example usage:
|
|
186
|
+
*
|
|
187
|
+
* console.log(`Processing: ${path.blue}`)
|
|
188
|
+
*
|
|
189
|
+
*/
|
|
190
|
+
get blue() {
|
|
191
|
+
const { styleText } = globalThis.process.getBuiltinModule("node:util");
|
|
192
|
+
return styleText(["bold", "blue"], this.#path);
|
|
193
|
+
}
|
|
182
194
|
/** Constructs a new path by appending the given path segments.
|
|
183
195
|
* This follows `node` semantics for absolute paths: leading slashes in the given descendant segments are ignored.
|
|
184
196
|
*/
|
|
@@ -499,7 +511,7 @@ var Path = class _Path {
|
|
|
499
511
|
);
|
|
500
512
|
return targetPath;
|
|
501
513
|
}
|
|
502
|
-
// I don't think `
|
|
514
|
+
// I don't think `realpath` is a great name, but it does match the
|
|
503
515
|
// well-established canonical commandline name. So in this case we keep the
|
|
504
516
|
// name instead of using `realPath`.
|
|
505
517
|
//
|
|
@@ -527,7 +539,7 @@ var Path = class _Path {
|
|
|
527
539
|
async chmodX() {
|
|
528
540
|
const { mode } = await this.stat();
|
|
529
541
|
await this.chmod(
|
|
530
|
-
mode | constants.
|
|
542
|
+
mode | constants.S_IXUSR | constants.S_IXGRP | constants.S_IXOTH
|
|
531
543
|
);
|
|
532
544
|
return this;
|
|
533
545
|
}
|
|
@@ -596,4 +608,4 @@ export {
|
|
|
596
608
|
stringifyIfPath,
|
|
597
609
|
mustNotHaveTrailingSlash
|
|
598
610
|
};
|
|
599
|
-
//# sourceMappingURL=chunk-
|
|
611
|
+
//# sourceMappingURL=chunk-QM7EHUFF.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/Path.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n appendFile,\n chmod,\n constants,\n cp,\n lstat,\n mkdir,\n mkdtemp,\n readdir,\n readFile,\n realpath,\n rename,\n rm,\n rmdir,\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 { cwd } from \"node:process\";\nimport { Readable } from \"node:stream\";\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\ntype WritableData = Parameters<typeof writeFile>[1] | ReadableStream | Response;\nasync function wrangleWritableData(\n data: WritableData | Promise<WritableData>,\n): Promise<Parameters<typeof writeFile>[1]> {\n data = await data;\n if (data instanceof Response) {\n data = data.body ? Readable.fromWeb(data.body) : new Uint8Array(0);\n }\n if (data instanceof ReadableStream) {\n data = Readable.fromWeb(data);\n }\n return data;\n}\n\nexport enum ResolutionPrefix {\n Absolute = \"absolute\",\n Relative = \"relative\",\n Bare = \"bare\",\n}\n\nexport function resolutionPrefix(pathString: string): ResolutionPrefix {\n if (pathString.startsWith(\"/\")) {\n return ResolutionPrefix.Absolute;\n } else if (pathString.startsWith(\"./\")) {\n return ResolutionPrefix.Relative;\n } else if (pathString.startsWith(\"../\")) {\n return ResolutionPrefix.Relative;\n } else if (pathString === \".\") {\n return ResolutionPrefix.Relative;\n } else if (pathString === \"..\") {\n return ResolutionPrefix.Relative;\n }\n return ResolutionPrefix.Bare;\n}\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 const s = Path.#pathlikeToString(path);\n this.#setNormalizedPath(s);\n }\n\n static fromString(s: string): Path {\n if (typeof s !== \"string\") {\n throw new Error(\n \"Invalid argument to `Path.fromString(\u2026)` \u2014 expected a string.\",\n );\n }\n return new Path(s);\n }\n\n get resolutionPrefix(): ResolutionPrefix {\n return resolutionPrefix(this.#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 if (typeof base === \"string\" && !base.startsWith(\"file://\")) {\n return pathToFileURL(base);\n }\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 // Preserves the `ResolutionPrefix` status when possible.\n #setNormalizedPath(path: string): void {\n const prefix = resolutionPrefix(path);\n this.#path = join(path);\n if (prefix === ResolutionPrefix.Relative && !this.#path.startsWith(\".\")) {\n // We don't have to handle the case of `\".\"`, as it already starts with `\".\"`\n this.#path = `./${this.#path}`;\n }\n }\n\n isAbsolutePath(): boolean {\n return this.resolutionPrefix === ResolutionPrefix.Absolute;\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 * Toggles or sets a trailing slash as specified.\n * If the path is `/`, it will always be left as-is.\n */\n // Similar convention to:\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle Most\n // use cases will probably use the `force` parameters, but supporting the\n // \"toggle\" use case is easy to implement and hopefully will make the name\n // and API more familiar to web devs.\n toggleTrailingSlash(force?: boolean): Path {\n if (this.#path === \"/\") {\n return this;\n }\n const wantTrailingSlash = force ?? !this.hasTrailingSlash();\n if (wantTrailingSlash) {\n return this.hasTrailingSlash() ? this : this.join(\"./\");\n } else {\n return this.hasTrailingSlash() ? new Path(this.#path.slice(0, -1)) : this;\n }\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 /**\n * Format this with the escape codes for printing to the shell in bold blue.\n *\n * Example usage:\n *\n * console.log(`Processing: ${path.blue}`)\n *\n */\n get blue() {\n const { styleText } = globalThis.process.getBuiltinModule(\"node:util\");\n return styleText([\"bold\", \"blue\"], 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 const s = stringifyIfPath(segment);\n if (resolutionPrefix(s) === ResolutionPrefix.Absolute) {\n throw new Error(\n \"Arguments to `.join(\u2026)` cannot be absolute. Use `.asRelative()` to convert them first if needed.\",\n );\n }\n return s;\n });\n return new Path(join(this.#path, ...segmentStrings));\n }\n\n /**\n * Adjust the prefix to construct a relative path.\n *\n * | Example input | Output |\n * |-----------------|-----------------|\n * | `\"bare\"` | `\"./bare\"` |\n * | `\"./relative\"` | `\"./relative\"` |\n * | `\"../up-first\"` | `\"../up-first\"` |\n * | `\"/absolute\"` | `\"./absolute\"` |\n *\n */\n asRelative(): Path {\n return new Path(`./${this.#path}`);\n }\n\n /**\n * Adjust the prefix to construct an absolute path.\n *\n * | Example input | Output |\n * |-----------------|---------------|\n * | `\"bare\"` | `\"/bare\"` |\n * | `\"./relative\"` | `\"/relative\"` |\n * | `\"../up-first\"` | `\"/up-first\"` |\n * | `\"/absolute\"` | `\"/absolute\"` |\n *\n */\n asAbsolute(): Path {\n return new Path(join(\"/\", this.#path));\n }\n\n /**\n * Adjust the prefix to construct a bare path. Note that this returns `\".\"` if\n * there are no named paths left.\n *\n * | Example input | Output |\n * |-------------------|--------------|\n * | `\"bare\"` | `\"bare\"` |\n * | `\"./relative\" ` | `\"relative\"` |\n * | `\"/absolute\"` | `\"absolute\"` |\n * | `\".\"` | `\".\"` |\n * | `\"down-first/..\"` | `\".\"` |\n * | `\"../up-first\"` | (error) |\n * | `\"..\"` | (error) |\n *\n * Specify `parentTraversalPrefixHandling` in the `options` if you would like\n * to strip or keep resolution prefixes like `../` rather than erroring.\n *\n * | Example input | Output with `{ parentTraversalPrefixHandling: \"strip\" }` |\n * |----------------------|----------------------------------------------------------|\n * | `\"../up-first\"` | `\"up-first\"` |\n * | `\"..\"` | `\".\"` |\n *\n * | Example input | Output with `{ parentTraversalPrefixHandling: \"keep\" }` |\n * |----------------------|---------------------------------------------------------|\n * | `\"../up-first\"` | `\"../up-first\"` |\n * | `\"..\"` | `\"..\"` |\n *\n * If you need the output to start with a named component and return values\n * like `.`, `..`, `../`, or `../\u2026` are not okay, pass\n * `requireNamedComponentPrefix: true`. This is useful if the path represents\n * an `npm`-style package name (e.g. `\"typescript\"`, `\"@biomejs/biome\"`).\n *\n */\n asBare(options?: {\n parentTraversalPrefixHandling?: \"error\" | \"strip\" | \"keep\";\n requireNamedComponentPrefix?: boolean;\n }): Path {\n const path = new Path(join(\".\", this.#path));\n if (!path.#path.startsWith(\"../\") && path.#path !== \"..\") {\n if (\n options?.requireNamedComponentPrefix &&\n path.resolutionPrefix === ResolutionPrefix.Relative\n ) {\n throw new Error(\"Output does not start with a named component.\");\n }\n return path;\n }\n const parentTraversalHandling =\n options?.parentTraversalPrefixHandling ?? \"error\";\n switch (parentTraversalHandling) {\n case \"error\": {\n throw new Error(\n 'Converting path to a bare path resulted in a `..` traversal prefix. Pass `\"strip\"` or `\"keep\"` as the `parentTraversalHandling` option to avoid an error.',\n );\n }\n case \"strip\": {\n let newPath = path.#path.replace(/^(\\.\\.\\/)+/, \"\");\n if ([\"\", \"..\"].includes(newPath)) {\n newPath = \".\";\n }\n const output = new Path(newPath);\n if (\n options?.requireNamedComponentPrefix &&\n output.resolutionPrefix === ResolutionPrefix.Relative\n ) {\n throw new Error(\"Output does not start with a named component.\");\n }\n return new Path(newPath);\n }\n case \"keep\": {\n if (options?.requireNamedComponentPrefix) {\n throw new Error(\"Output does not start with a named component.\");\n }\n return path;\n }\n }\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 if (constraints?.mustBe === \"file\") {\n mustNotHaveTrailingSlash(this);\n }\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 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 /**\n * Create a temporary dir inside the global temp dir for the current user.\n *\n * This can be used with [`await\n * using`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/await_using)\n * to automatically delete the dir when it goes out of scope.\n *\n * {\n * await using tempDir = await Path.makeTempDir();\n * // Temporary dir exists while we're inside this block.\n * }\n * // Temporary dir has now been deleted.\n *\n * Note that (due to the semantics of JS runtime implementations) this does\n * not delete the temp dir if the process calls `exit(\u2026)` before the `using`\n * goes out of scope.\n *\n * */\n static async makeTempDir(prefix?: string): Promise<AsyncDisposablePath> {\n return new AsyncDisposablePath(\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 async rmDir(): Promise<void> {\n await rmdir(this.#path);\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 /**\n * Reads JSON from the given file and parses it. No validation is performed\n * (beyond JSON parsing).\n *\n * An optional `fallback` value can be specified. It will be used if (and only\n * if) the file does not exist.\n *\n */\n\n // biome-ignore lint/suspicious/noExplicitAny: Allow a default of `any` to match `JSON.parse(\u2026)`.\n async readJSON<T = any>(options?: { fallback?: T }): Promise<T> {\n try {\n return JSON.parse(await this.readText());\n } catch (e) {\n if (\n (e as { code?: string }).code === \"ENOENT\" &&\n options &&\n \"fallback\" in options\n ) {\n return options.fallback as T;\n }\n throw e;\n }\n }\n\n /**\n * Returns the original `Path` (for chaining).\n */\n async appendFile(\n data: Parameters<typeof appendFile>[1],\n options?: Parameters<typeof appendFile>[2],\n ): Promise<Path> {\n await appendFile(this.#path, data, options);\n return this;\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: WritableData | Promise<WritableData>,\n options?: Parameters<typeof writeFile>[2],\n ): Promise<Path> {\n await this.parent.mkdir();\n await writeFile(this.#path, await wrangleWritableData(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 // I don't think `realpath` is a great name, but it does match the\n // well-established canonical commandline name. So in this case we keep the\n // name instead of using `realPath`.\n //\n // Note: There are no options in our API, because the only option is an\n // encoding. We set the encoding to construct the returned `Path`.\n async realpath(): Promise<Path> {\n return new Path(await realpath(this.#path, \"utf-8\"));\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 async chmod(mode: Parameters<typeof chmod>[1]): Promise<Path> {\n await chmod(this.#path, mode);\n return this;\n }\n\n /**\n * Add the executable bit (for everyone) to the given path without modifying other bits (`chmod +x`).\n */\n async chmodX(): Promise<Path> {\n const { mode } = await this.stat();\n await this.chmod(\n mode | constants.S_IXUSR | constants.S_IXGRP | constants.S_IXOTH,\n );\n return this;\n }\n\n static get homedir(): Path {\n return new Path(homedir());\n }\n\n /**\n * Get the current working directory as a path. Always includes a trailing slash.\n * Note that this computes the `cwd` from fresh every time, in case it has changed for the current process.\n */\n static get cwd(): Path {\n return new Path(cwd()).toggleTrailingSlash(true);\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\nexport class AsyncDisposablePath extends Path {\n async [Symbol.asyncDispose]() {\n await this.rm_rf();\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": ["ResolutionPrefix"]
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Path,
|
|
3
3
|
mustNotHaveTrailingSlash
|
|
4
|
-
} from "../chunks/chunk-
|
|
4
|
+
} from "../chunks/chunk-QM7EHUFF.js";
|
|
5
5
|
|
|
6
6
|
// src/sync/PathSync.ts
|
|
7
7
|
import {
|
|
@@ -202,7 +202,7 @@ var PathSync = class _PathSync extends Path {
|
|
|
202
202
|
chmodXSync() {
|
|
203
203
|
const { mode } = this.statSync();
|
|
204
204
|
this.chmodSync(
|
|
205
|
-
mode | constants.
|
|
205
|
+
mode | constants.S_IXUSR | constants.S_IXGRP | constants.S_IXOTH
|
|
206
206
|
);
|
|
207
207
|
return this;
|
|
208
208
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/sync/PathSync.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n appendFileSync,\n chmodSync,\n cpSync,\n lstatSync,\n mkdirSync,\n mkdtempSync,\n readdirSync,\n readFileSync,\n realpathSync,\n renameSync,\n rmdirSync,\n rmSync,\n statSync,\n symlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { constants } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { mustNotHaveTrailingSlash, Path } from \"../Path\";\nimport type {\n lstatSyncType,\n readDirSyncType,\n readFileSyncType,\n statSyncType,\n} from \"./modifiedNodeTypes\";\n\nexport class PathSync extends Path {\n static override fromString(s: string): PathSync {\n return new PathSync(s);\n }\n\n static override resolve(...args: Parameters<typeof Path.resolve>): PathSync {\n return new PathSync(Path.resolve(...args));\n }\n\n override toggleTrailingSlash(\n ...args: Parameters<Path[\"toggleTrailingSlash\"]>\n ): PathSync {\n return new PathSync(super.toggleTrailingSlash(...args));\n }\n\n override join(...args: Parameters<Path[\"join\"]>): PathSync {\n return new PathSync(super.join(...args));\n }\n\n override asRelative(...args: Parameters<Path[\"asRelative\"]>): PathSync {\n return new PathSync(super.asRelative(...args));\n }\n\n override asAbsolute(...args: Parameters<Path[\"asAbsolute\"]>): PathSync {\n return new PathSync(super.asAbsolute(...args));\n }\n\n override asBare(...args: Parameters<Path[\"asBare\"]>): PathSync {\n return new PathSync(super.asBare(...args));\n }\n\n override extendBasename(\n ...args: Parameters<Path[\"extendBasename\"]>\n ): PathSync {\n return new PathSync(super.extendBasename(...args));\n }\n\n override get parent(): PathSync {\n return new PathSync(super.parent);\n }\n\n override get dirname(): PathSync {\n return new PathSync(super.dirname);\n }\n\n override get basename(): PathSync {\n return new PathSync(super.basename);\n }\n\n static override get homedir(): PathSync {\n return new PathSync(Path.homedir);\n }\n\n static override get cwd(): PathSync {\n return new PathSync(Path.cwd);\n }\n\n override debugPrint(...args: Parameters<Path[\"debugPrint\"]>): PathSync {\n return new PathSync(super.debugPrint(...args));\n }\n\n // TODO: find a neat way to dedup with the async version? // lint-sync-code-expect-error\n existsSync(constraints?: { mustBe: \"file\" | \"directory\" }): boolean {\n if (constraints?.mustBe === \"file\") {\n mustNotHaveTrailingSlash(this);\n }\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 if (stats.isFile()) {\n return true;\n }\n throw new Error(`PathSync exists but is not a file: ${this.path}`);\n }\n case \"directory\": {\n if (stats.isDirectory()) {\n return true;\n }\n throw new Error(`PathSync exists but is not a directory: ${this.path}`);\n }\n default: {\n throw new Error(\"Invalid path type constraint\");\n }\n }\n }\n\n existsAsFileSync(): boolean {\n return this.existsSync({ mustBe: \"file\" });\n }\n\n existsAsDirSync(): boolean {\n return this.existsSync({ mustBe: \"directory\" });\n }\n\n mkdirSync(options?: Parameters<typeof mkdirSync>[1]): PathSync {\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\n cpSync(\n destination: string | URL | Path,\n options?: Parameters<typeof cpSync>[2],\n ): PathSync {\n cpSync(this.path, new Path(destination).path, options);\n return new PathSync(destination);\n }\n\n renameSync(destination: string | URL | Path): void {\n renameSync(this.path, new Path(destination).path);\n }\n\n static makeTempDirSync(prefix?: string): PathSync {\n return new PathSync(\n mkdtempSync(new Path(tmpdir()).join(prefix ?? \"js-temp-\").toString()),\n );\n }\n\n rmSync(options?: Parameters<typeof rmSync>[1]): void {\n rmSync(this.path, options);\n }\n\n rmDirSync(): void {\n rmdirSync(this.path);\n }\n\n rm_rfSync(options?: Parameters<typeof rmSync>[1]): void {\n this.rmSync({ recursive: true, force: true, ...(options ?? {}) });\n }\n\n readSync: typeof readFileSyncType = (options) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n readFileSync(this.path, options) as any;\n\n readTextSync(): string {\n return readFileSync(this.path, \"utf-8\");\n }\n\n readJSONSync<T>(options?: { fallback?: T }): T {\n try {\n return JSON.parse(this.readTextSync());\n } catch (e) {\n if (\n (e as { code?: string }).code === \"ENOENT\" &&\n options &&\n \"fallback\" in options\n ) {\n return options.fallback as T;\n }\n throw e;\n }\n }\n\n appendFileSync(\n data: Parameters<typeof appendFileSync>[1],\n options?: Parameters<typeof appendFileSync>[2],\n ): PathSync {\n appendFileSync(this.path, data, options);\n return this;\n }\n\n writeSync(\n data: Parameters<typeof writeFileSync>[1],\n options?: Parameters<typeof writeFileSync>[2],\n ): PathSync {\n this.parent.mkdirSync();\n writeFileSync(this.path, data, options);\n return this;\n }\n\n writeJSONSync<T>(\n data: T,\n replacer: Parameters<typeof JSON.stringify>[1] = null,\n space: Parameters<typeof JSON.stringify>[2] = \" \",\n ): PathSync {\n this.parent.mkdirSync();\n this.writeSync(JSON.stringify(data, replacer, space));\n return this;\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Type wrangling.\n readDirSync: typeof readDirSyncType = (options: any) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n readdirSync(this.path, options) as any;\n\n symlinkSync(\n target: string | URL | Path,\n type?: Parameters<typeof symlinkSync>[2],\n ): PathSync {\n const targetPath = new PathSync(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 realpathSync(): PathSync {\n return new PathSync(realpathSync(this.path));\n }\n\n statSync: typeof statSyncType = (options) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n statSync(this.path, options) as any;\n\n lstatSync: typeof lstatSyncType = (options) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n lstatSync(this.path, options) as any;\n\n chmodSync(mode: Parameters<typeof chmodSync>[1]): PathSync {\n chmodSync(this.path, mode);\n return this;\n }\n\n chmodXSync(): PathSync {\n const { mode } = this.statSync();\n this.chmodSync(\n mode
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import {\n appendFileSync,\n chmodSync,\n cpSync,\n lstatSync,\n mkdirSync,\n mkdtempSync,\n readdirSync,\n readFileSync,\n realpathSync,\n renameSync,\n rmdirSync,\n rmSync,\n statSync,\n symlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { constants } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { mustNotHaveTrailingSlash, Path } from \"../Path\";\nimport type {\n lstatSyncType,\n readDirSyncType,\n readFileSyncType,\n statSyncType,\n} from \"./modifiedNodeTypes\";\n\nexport class PathSync extends Path {\n static override fromString(s: string): PathSync {\n return new PathSync(s);\n }\n\n static override resolve(...args: Parameters<typeof Path.resolve>): PathSync {\n return new PathSync(Path.resolve(...args));\n }\n\n override toggleTrailingSlash(\n ...args: Parameters<Path[\"toggleTrailingSlash\"]>\n ): PathSync {\n return new PathSync(super.toggleTrailingSlash(...args));\n }\n\n override join(...args: Parameters<Path[\"join\"]>): PathSync {\n return new PathSync(super.join(...args));\n }\n\n override asRelative(...args: Parameters<Path[\"asRelative\"]>): PathSync {\n return new PathSync(super.asRelative(...args));\n }\n\n override asAbsolute(...args: Parameters<Path[\"asAbsolute\"]>): PathSync {\n return new PathSync(super.asAbsolute(...args));\n }\n\n override asBare(...args: Parameters<Path[\"asBare\"]>): PathSync {\n return new PathSync(super.asBare(...args));\n }\n\n override extendBasename(\n ...args: Parameters<Path[\"extendBasename\"]>\n ): PathSync {\n return new PathSync(super.extendBasename(...args));\n }\n\n override get parent(): PathSync {\n return new PathSync(super.parent);\n }\n\n override get dirname(): PathSync {\n return new PathSync(super.dirname);\n }\n\n override get basename(): PathSync {\n return new PathSync(super.basename);\n }\n\n static override get homedir(): PathSync {\n return new PathSync(Path.homedir);\n }\n\n static override get cwd(): PathSync {\n return new PathSync(Path.cwd);\n }\n\n override debugPrint(...args: Parameters<Path[\"debugPrint\"]>): PathSync {\n return new PathSync(super.debugPrint(...args));\n }\n\n // TODO: find a neat way to dedup with the async version? // lint-sync-code-expect-error\n existsSync(constraints?: { mustBe: \"file\" | \"directory\" }): boolean {\n if (constraints?.mustBe === \"file\") {\n mustNotHaveTrailingSlash(this);\n }\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 if (stats.isFile()) {\n return true;\n }\n throw new Error(`PathSync exists but is not a file: ${this.path}`);\n }\n case \"directory\": {\n if (stats.isDirectory()) {\n return true;\n }\n throw new Error(`PathSync exists but is not a directory: ${this.path}`);\n }\n default: {\n throw new Error(\"Invalid path type constraint\");\n }\n }\n }\n\n existsAsFileSync(): boolean {\n return this.existsSync({ mustBe: \"file\" });\n }\n\n existsAsDirSync(): boolean {\n return this.existsSync({ mustBe: \"directory\" });\n }\n\n mkdirSync(options?: Parameters<typeof mkdirSync>[1]): PathSync {\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\n cpSync(\n destination: string | URL | Path,\n options?: Parameters<typeof cpSync>[2],\n ): PathSync {\n cpSync(this.path, new Path(destination).path, options);\n return new PathSync(destination);\n }\n\n renameSync(destination: string | URL | Path): void {\n renameSync(this.path, new Path(destination).path);\n }\n\n static makeTempDirSync(prefix?: string): PathSync {\n return new PathSync(\n mkdtempSync(new Path(tmpdir()).join(prefix ?? \"js-temp-\").toString()),\n );\n }\n\n rmSync(options?: Parameters<typeof rmSync>[1]): void {\n rmSync(this.path, options);\n }\n\n rmDirSync(): void {\n rmdirSync(this.path);\n }\n\n rm_rfSync(options?: Parameters<typeof rmSync>[1]): void {\n this.rmSync({ recursive: true, force: true, ...(options ?? {}) });\n }\n\n readSync: typeof readFileSyncType = (options) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n readFileSync(this.path, options) as any;\n\n readTextSync(): string {\n return readFileSync(this.path, \"utf-8\");\n }\n\n readJSONSync<T>(options?: { fallback?: T }): T {\n try {\n return JSON.parse(this.readTextSync());\n } catch (e) {\n if (\n (e as { code?: string }).code === \"ENOENT\" &&\n options &&\n \"fallback\" in options\n ) {\n return options.fallback as T;\n }\n throw e;\n }\n }\n\n appendFileSync(\n data: Parameters<typeof appendFileSync>[1],\n options?: Parameters<typeof appendFileSync>[2],\n ): PathSync {\n appendFileSync(this.path, data, options);\n return this;\n }\n\n writeSync(\n data: Parameters<typeof writeFileSync>[1],\n options?: Parameters<typeof writeFileSync>[2],\n ): PathSync {\n this.parent.mkdirSync();\n writeFileSync(this.path, data, options);\n return this;\n }\n\n writeJSONSync<T>(\n data: T,\n replacer: Parameters<typeof JSON.stringify>[1] = null,\n space: Parameters<typeof JSON.stringify>[2] = \" \",\n ): PathSync {\n this.parent.mkdirSync();\n this.writeSync(JSON.stringify(data, replacer, space));\n return this;\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: Type wrangling.\n readDirSync: typeof readDirSyncType = (options: any) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n readdirSync(this.path, options) as any;\n\n symlinkSync(\n target: string | URL | Path,\n type?: Parameters<typeof symlinkSync>[2],\n ): PathSync {\n const targetPath = new PathSync(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 realpathSync(): PathSync {\n return new PathSync(realpathSync(this.path));\n }\n\n statSync: typeof statSyncType = (options) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n statSync(this.path, options) as any;\n\n lstatSync: typeof lstatSyncType = (options) =>\n // biome-ignore lint/suspicious/noExplicitAny: Needed to wrangle the types.\n lstatSync(this.path, options) as any;\n\n chmodSync(mode: Parameters<typeof chmodSync>[1]): PathSync {\n chmodSync(this.path, mode);\n return this;\n }\n\n chmodXSync(): PathSync {\n const { mode } = this.statSync();\n this.chmodSync(\n mode | constants.S_IXUSR | constants.S_IXGRP | constants.S_IXOTH,\n );\n return this;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "path-class",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "A semantic `Path` class for `node` and `bun`. Inspired by `bun`'s [`file(…)`](https://bun.com/docs/runtime/file-io) API, but `node`-compatible.",
|
|
5
5
|
"author": "Lucas Garron <code@garron.net>",
|
|
6
6
|
"license": "MIT",
|
package/src/Path.test.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { expect, spyOn, test } from "bun:test";
|
|
2
|
-
import { readFile, realpath } from "node:fs/promises";
|
|
2
|
+
import { constants, readFile, realpath } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { chdir } from "node:process";
|
|
5
5
|
import { PrintableShellCommand } from "printable-shell-command";
|
|
6
6
|
import { Path, ResolutionPrefix, stringifyIfPath } from "./Path";
|
|
7
7
|
|
|
8
|
-
test("constructor", async () => {
|
|
8
|
+
test.concurrent("constructor", async () => {
|
|
9
9
|
expect(new Path("bare").path).toEqual("bare");
|
|
10
10
|
expect(new Path("bare/").path).toEqual("bare/");
|
|
11
11
|
expect(new Path("bare/path").path).toEqual("bare/path");
|
|
@@ -27,7 +27,7 @@ test("constructor", async () => {
|
|
|
27
27
|
expect(new Path(new Path("foo")).path).toEqual("foo");
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
test(".fromString(…)", async () => {
|
|
30
|
+
test.concurrent(".fromString(…)", async () => {
|
|
31
31
|
expect(Path.fromString("bare").path).toEqual("bare");
|
|
32
32
|
// biome-ignore lint/suspicious/noExplicitAny: We're purposely passing an invalid type.
|
|
33
33
|
expect(() => Path.fromString(new URL("file:///test") as any)).toThrow(
|
|
@@ -35,7 +35,7 @@ test(".fromString(…)", async () => {
|
|
|
35
35
|
);
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
test(".resolutionPrefix", async () => {
|
|
38
|
+
test.concurrent(".resolutionPrefix", async () => {
|
|
39
39
|
expect(new Path("bare").resolutionPrefix).toEqual(ResolutionPrefix.Bare);
|
|
40
40
|
expect(new Path("bare/").resolutionPrefix).toEqual(ResolutionPrefix.Bare);
|
|
41
41
|
expect(new Path("bare/path").resolutionPrefix).toEqual(ResolutionPrefix.Bare);
|
|
@@ -79,7 +79,7 @@ test(".resolutionPrefix", async () => {
|
|
|
79
79
|
expect(new Path("../").resolutionPrefix).toEqual(ResolutionPrefix.Relative);
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
-
test("Path.resolve(…)", async () => {
|
|
82
|
+
test.concurrent("Path.resolve(…)", async () => {
|
|
83
83
|
expect(Path.resolve("foo/lish", new Path("/bar/baz")).path).toEqual(
|
|
84
84
|
"/bar/foo/lish",
|
|
85
85
|
);
|
|
@@ -95,13 +95,13 @@ test("Path.resolve(…)", async () => {
|
|
|
95
95
|
);
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
test(".isAbsolutePath()", async () => {
|
|
98
|
+
test.concurrent(".isAbsolutePath()", async () => {
|
|
99
99
|
expect(new Path("/foo/bar").isAbsolutePath()).toBe(true);
|
|
100
100
|
expect(new Path("foo/bar").isAbsolutePath()).toBe(false);
|
|
101
101
|
expect(new Path(import.meta.url).isAbsolutePath()).toBe(true);
|
|
102
102
|
});
|
|
103
103
|
|
|
104
|
-
test(".toFileURL()", async () => {
|
|
104
|
+
test.concurrent(".toFileURL()", async () => {
|
|
105
105
|
expect(new Path("/foo/bar").toFileURL().toString()).toEqual(
|
|
106
106
|
"file:///foo/bar",
|
|
107
107
|
);
|
|
@@ -111,7 +111,7 @@ test(".toFileURL()", async () => {
|
|
|
111
111
|
);
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
-
test(".hasTrailingSlash()", async () => {
|
|
114
|
+
test.concurrent(".hasTrailingSlash()", async () => {
|
|
115
115
|
expect(new Path("/foo/bar").hasTrailingSlash()).toBe(false);
|
|
116
116
|
expect(new Path("/foo/bar/").hasTrailingSlash()).toBe(true);
|
|
117
117
|
expect(new Path("foo/bar").hasTrailingSlash()).toBe(false);
|
|
@@ -124,7 +124,7 @@ test(".hasTrailingSlash()", async () => {
|
|
|
124
124
|
expect(new Path(import.meta.url).join(".").hasTrailingSlash()).toBe(false);
|
|
125
125
|
});
|
|
126
126
|
|
|
127
|
-
test(".toggleTrailingSlash(…)", async () => {
|
|
127
|
+
test.concurrent(".toggleTrailingSlash(…)", async () => {
|
|
128
128
|
expect(new Path("/foo/bar").toggleTrailingSlash().path).toBe("/foo/bar/");
|
|
129
129
|
expect(new Path("/foo/bar/").toggleTrailingSlash().path).toBe("/foo/bar");
|
|
130
130
|
expect(new Path("/").toggleTrailingSlash().path).toBe("/");
|
|
@@ -134,7 +134,14 @@ test(".toggleTrailingSlash(…)", async () => {
|
|
|
134
134
|
expect(new Path("..").toggleTrailingSlash().path).toBe("../");
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
test("
|
|
137
|
+
test.concurrent(".blue", async () => {
|
|
138
|
+
expect(Path.fromString("bare").path).toEqual("bare");
|
|
139
|
+
expect(`Home dir: ${Path.homedir.blue}`).toEqual(
|
|
140
|
+
"Home dir: \u001b[1m\u001b[34m/mock/home/dir\u001b[39m\u001b[22m",
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test.concurrent("normalize", async () => {
|
|
138
145
|
expect(new Path("foo//bar").path).toEqual("foo/bar");
|
|
139
146
|
expect(new Path("foo////bar").path).toEqual("foo/bar");
|
|
140
147
|
expect(new Path("foo/bar/").path).toEqual("foo/bar/");
|
|
@@ -142,7 +149,7 @@ test("normalize", async () => {
|
|
|
142
149
|
expect(new Path("//absolute////bar").path).toEqual("/absolute/bar");
|
|
143
150
|
});
|
|
144
151
|
|
|
145
|
-
test(".join(…)", async () => {
|
|
152
|
+
test.concurrent(".join(…)", async () => {
|
|
146
153
|
expect(new Path("foo").join("bar").path).toEqual("foo/bar");
|
|
147
154
|
expect(new Path("foo/bar").join("bath", "kitchen/sink").path).toEqual(
|
|
148
155
|
"foo/bar/bath/kitchen/sink",
|
|
@@ -156,7 +163,7 @@ test(".join(…)", async () => {
|
|
|
156
163
|
);
|
|
157
164
|
});
|
|
158
165
|
|
|
159
|
-
test("asRelative()", async () => {
|
|
166
|
+
test.concurrent("asRelative()", async () => {
|
|
160
167
|
// From doc comment
|
|
161
168
|
expect(new Path("bare").asRelative().path).toEqual("./bare");
|
|
162
169
|
expect(new Path("./relative").asRelative().path).toEqual("./relative");
|
|
@@ -174,7 +181,7 @@ test("asRelative()", async () => {
|
|
|
174
181
|
expect(new Path("../up/").asRelative().path).toEqual("../up/");
|
|
175
182
|
});
|
|
176
183
|
|
|
177
|
-
test("asAbsolute()", async () => {
|
|
184
|
+
test.concurrent("asAbsolute()", async () => {
|
|
178
185
|
// From doc comment
|
|
179
186
|
expect(new Path("bare").asAbsolute().path).toEqual("/bare");
|
|
180
187
|
expect(new Path("./relative").asAbsolute().path).toEqual("/relative");
|
|
@@ -186,7 +193,7 @@ test("asAbsolute()", async () => {
|
|
|
186
193
|
expect(new Path("../up/").asAbsolute().path).toEqual("/up/");
|
|
187
194
|
});
|
|
188
195
|
|
|
189
|
-
test("asBare(…)", async () => {
|
|
196
|
+
test.concurrent("asBare(…)", async () => {
|
|
190
197
|
const ERROR_1 =
|
|
191
198
|
'Converting path to a bare path resulted in a `..` traversal prefix. Pass `"strip"` or `"keep"` as the `parentTraversalHandling` option to avoid an error.';
|
|
192
199
|
const ERROR_2 = "Output does not start with a named component.";
|
|
@@ -261,7 +268,7 @@ test("asBare(…)", async () => {
|
|
|
261
268
|
).toThrow(ERROR_2);
|
|
262
269
|
});
|
|
263
270
|
|
|
264
|
-
test("traverse", async () => {
|
|
271
|
+
test.concurrent("traverse", async () => {
|
|
265
272
|
expect(new Path("foo/bar").join("..").path).toEqual("foo");
|
|
266
273
|
expect(new Path("foo/bar").join(".").path).toEqual("foo/bar");
|
|
267
274
|
expect(new Path("foo/bar").join("../baz").path).toEqual("foo/baz");
|
|
@@ -270,7 +277,7 @@ test("traverse", async () => {
|
|
|
270
277
|
expect(new Path("/").join("..").path).toEqual("/");
|
|
271
278
|
});
|
|
272
279
|
|
|
273
|
-
test(".extendBasename(…)", async () => {
|
|
280
|
+
test.concurrent(".extendBasename(…)", async () => {
|
|
274
281
|
expect(new Path("file.mp4").extendBasename(".hevc.qv65.mov").path).toEqual(
|
|
275
282
|
"file.mp4.hevc.qv65.mov",
|
|
276
283
|
);
|
|
@@ -280,19 +287,19 @@ test(".extendBasename(…)", async () => {
|
|
|
280
287
|
);
|
|
281
288
|
});
|
|
282
289
|
|
|
283
|
-
test(".parent", async () => {
|
|
290
|
+
test.concurrent(".parent", async () => {
|
|
284
291
|
expect(new Path("/").parent.path).toEqual("/");
|
|
285
292
|
expect(new Path("dir").parent.path).toEqual(".");
|
|
286
293
|
expect(new Path("dir/").parent.path).toEqual(".");
|
|
287
294
|
});
|
|
288
295
|
|
|
289
|
-
test(".dirname", async () => {
|
|
296
|
+
test.concurrent(".dirname", async () => {
|
|
290
297
|
expect(new Path("/").dirname.path).toEqual("/");
|
|
291
298
|
expect(new Path("dir").dirname.path).toEqual(".");
|
|
292
299
|
expect(new Path("dir/").dirname.path).toEqual(".");
|
|
293
300
|
});
|
|
294
301
|
|
|
295
|
-
test(".basename", async () => {
|
|
302
|
+
test.concurrent(".basename", async () => {
|
|
296
303
|
expect(new Path("/").basename.path).toEqual("."); // TODO?
|
|
297
304
|
expect(new Path("dir").basename.path).toEqual("dir");
|
|
298
305
|
expect(new Path("dir/").basename.path).toEqual("dir");
|
|
@@ -301,7 +308,7 @@ test(".basename", async () => {
|
|
|
301
308
|
);
|
|
302
309
|
});
|
|
303
310
|
|
|
304
|
-
test(".extension", async () => {
|
|
311
|
+
test.concurrent(".extension", async () => {
|
|
305
312
|
expect(new Path("foo.txt").extension).toEqual(".txt");
|
|
306
313
|
expect(new Path("foo.").extension).toEqual(".");
|
|
307
314
|
expect(new Path("foo").extension).toEqual("");
|
|
@@ -309,7 +316,7 @@ test(".extension", async () => {
|
|
|
309
316
|
expect(() => new Path("/").extension).toThrow();
|
|
310
317
|
});
|
|
311
318
|
|
|
312
|
-
test(".extname", async () => {
|
|
319
|
+
test.concurrent(".extname", async () => {
|
|
313
320
|
expect(new Path("foo.txt").extname).toEqual(".txt");
|
|
314
321
|
expect(new Path("foo.").extname).toEqual(".");
|
|
315
322
|
expect(new Path("foo").extname).toEqual("");
|
|
@@ -317,7 +324,7 @@ test(".extname", async () => {
|
|
|
317
324
|
expect(() => new Path("/").extname).toThrow();
|
|
318
325
|
});
|
|
319
326
|
|
|
320
|
-
test(".existsAsFile()", async () => {
|
|
327
|
+
test.concurrent(".existsAsFile()", async () => {
|
|
321
328
|
const filePath = (await Path.makeTempDir()).join("file.txt");
|
|
322
329
|
expect(await filePath.exists()).toBe(false);
|
|
323
330
|
expect(await filePath.exists({ mustBe: "file" })).toBe(false);
|
|
@@ -335,7 +342,7 @@ test(".existsAsFile()", async () => {
|
|
|
335
342
|
expect(await filePath.existsAsFile()).toBe(true);
|
|
336
343
|
});
|
|
337
344
|
|
|
338
|
-
test(".existsAsDir()", async () => {
|
|
345
|
+
test.concurrent(".existsAsDir()", async () => {
|
|
339
346
|
const filePath = await Path.makeTempDir();
|
|
340
347
|
expect(await filePath.exists()).toBe(true);
|
|
341
348
|
expect(() => filePath.exists({ mustBe: "file" })).toThrow(
|
|
@@ -350,14 +357,14 @@ test(".existsAsDir()", async () => {
|
|
|
350
357
|
expect(await filePath.existsAsDir()).toBe(false);
|
|
351
358
|
});
|
|
352
359
|
|
|
353
|
-
test(".mkdir(…) (un-nested)", async () => {
|
|
360
|
+
test.concurrent(".mkdir(…) (un-nested)", async () => {
|
|
354
361
|
const dir = (await Path.makeTempDir()).join("mkdir-test");
|
|
355
362
|
expect(await dir.exists()).toBe(false);
|
|
356
363
|
await dir.mkdir();
|
|
357
364
|
expect(await dir.exists()).toBe(true);
|
|
358
365
|
});
|
|
359
366
|
|
|
360
|
-
test(".mkdir(…) (nested)", async () => {
|
|
367
|
+
test.concurrent(".mkdir(…) (nested)", async () => {
|
|
361
368
|
const dir = (await Path.makeTempDir()).join("mkdir-test/nested");
|
|
362
369
|
expect(await dir.exists()).toBe(false);
|
|
363
370
|
expect(() => dir.mkdir({ recursive: false })).toThrow("no such file");
|
|
@@ -365,7 +372,7 @@ test(".mkdir(…) (nested)", async () => {
|
|
|
365
372
|
expect(await dir.exists()).toBe(true);
|
|
366
373
|
});
|
|
367
374
|
|
|
368
|
-
test(".cp(…)", async () => {
|
|
375
|
+
test.concurrent(".cp(…)", async () => {
|
|
369
376
|
const parentDir = await Path.makeTempDir();
|
|
370
377
|
const file1 = parentDir.join("file1.txt");
|
|
371
378
|
const file2 = parentDir.join("file2.txt");
|
|
@@ -379,7 +386,7 @@ test(".cp(…)", async () => {
|
|
|
379
386
|
expect(await file2.exists()).toBe(true);
|
|
380
387
|
});
|
|
381
388
|
|
|
382
|
-
test(".rename(…)", async () => {
|
|
389
|
+
test.concurrent(".rename(…)", async () => {
|
|
383
390
|
const parentDir = await Path.makeTempDir();
|
|
384
391
|
const file1 = parentDir.join("file1.txt");
|
|
385
392
|
const file2 = parentDir.join("file2.txt");
|
|
@@ -393,7 +400,7 @@ test(".rename(…)", async () => {
|
|
|
393
400
|
expect(await file2.exists()).toBe(true);
|
|
394
401
|
});
|
|
395
402
|
|
|
396
|
-
test(".makeTempDir(…)", async () => {
|
|
403
|
+
test.concurrent(".makeTempDir(…)", async () => {
|
|
397
404
|
let asyncDisposablePathString: string;
|
|
398
405
|
{
|
|
399
406
|
await using tempDir = await Path.makeTempDir();
|
|
@@ -414,7 +421,7 @@ test(".makeTempDir(…)", async () => {
|
|
|
414
421
|
expect(await new Path(asyncDisposablePathString2).existsAsDir()).toBe(false);
|
|
415
422
|
});
|
|
416
423
|
|
|
417
|
-
test(".rm(…) (file)", async () => {
|
|
424
|
+
test.concurrent(".rm(…) (file)", async () => {
|
|
418
425
|
const file = (await Path.makeTempDir()).join("file.txt");
|
|
419
426
|
await file.write("");
|
|
420
427
|
expect(await file.existsAsFile()).toBe(true);
|
|
@@ -424,7 +431,7 @@ test(".rm(…) (file)", async () => {
|
|
|
424
431
|
expect(async () => file.rm()).toThrowError(/ENOENT/);
|
|
425
432
|
});
|
|
426
433
|
|
|
427
|
-
test(".rm(…) (folder)", async () => {
|
|
434
|
+
test.concurrent(".rm(…) (folder)", async () => {
|
|
428
435
|
const tempDir = await Path.makeTempDir();
|
|
429
436
|
const file = tempDir.join("file.txt");
|
|
430
437
|
await file.write("");
|
|
@@ -436,7 +443,7 @@ test(".rm(…) (folder)", async () => {
|
|
|
436
443
|
expect(async () => tempDir.rm()).toThrowError(/ENOENT/);
|
|
437
444
|
});
|
|
438
445
|
|
|
439
|
-
test(".rmDir(…)", async () => {
|
|
446
|
+
test.concurrent(".rmDir(…)", async () => {
|
|
440
447
|
const tempDir = await Path.makeTempDir();
|
|
441
448
|
const file = tempDir.join("file.txt");
|
|
442
449
|
await file.write("");
|
|
@@ -448,7 +455,7 @@ test(".rmDir(…)", async () => {
|
|
|
448
455
|
expect(async () => tempDir.rmDir()).toThrowError(/ENOENT/);
|
|
449
456
|
});
|
|
450
457
|
|
|
451
|
-
test(".rm_rf(…) (file)", async () => {
|
|
458
|
+
test.concurrent(".rm_rf(…) (file)", async () => {
|
|
452
459
|
const file = (await Path.makeTempDir()).join("file.txt");
|
|
453
460
|
await file.write("");
|
|
454
461
|
expect(await file.existsAsFile()).toBe(true);
|
|
@@ -459,7 +466,7 @@ test(".rm_rf(…) (file)", async () => {
|
|
|
459
466
|
expect(await file.existsAsFile()).toBe(false);
|
|
460
467
|
});
|
|
461
468
|
|
|
462
|
-
test(".rm_rf(…) (folder)", async () => {
|
|
469
|
+
test.concurrent(".rm_rf(…) (folder)", async () => {
|
|
463
470
|
const tempDir = await Path.makeTempDir();
|
|
464
471
|
await tempDir.join("file.txt").write("");
|
|
465
472
|
expect(tempDir.path).toContain("/js-temp-");
|
|
@@ -470,7 +477,7 @@ test(".rm_rf(…) (folder)", async () => {
|
|
|
470
477
|
expect(await tempDir.exists()).toBe(false);
|
|
471
478
|
});
|
|
472
479
|
|
|
473
|
-
test(".readText()", async () => {
|
|
480
|
+
test.concurrent(".readText()", async () => {
|
|
474
481
|
const file = (await Path.makeTempDir()).join("file.txt");
|
|
475
482
|
await file.write("hi");
|
|
476
483
|
await file.write("bye");
|
|
@@ -479,7 +486,7 @@ test(".readText()", async () => {
|
|
|
479
486
|
expect(await readFile(file.path, "utf-8")).toBe("bye");
|
|
480
487
|
});
|
|
481
488
|
|
|
482
|
-
test(".readJSON()", async () => {
|
|
489
|
+
test.concurrent(".readJSON()", async () => {
|
|
483
490
|
const file = (await Path.makeTempDir()).join("file.json");
|
|
484
491
|
await file.write(JSON.stringify({ foo: "bar" }));
|
|
485
492
|
|
|
@@ -490,7 +497,7 @@ test(".readJSON()", async () => {
|
|
|
490
497
|
>({ foo: "bar" });
|
|
491
498
|
});
|
|
492
499
|
|
|
493
|
-
test(".readJSON(…) with fallback", async () => {
|
|
500
|
+
test.concurrent(".readJSON(…) with fallback", async () => {
|
|
494
501
|
const tempDir = await Path.makeTempDir();
|
|
495
502
|
const file = tempDir.join("file.json");
|
|
496
503
|
const json: { foo?: number } = await file.readJSON({ fallback: { foo: 4 } });
|
|
@@ -508,7 +515,7 @@ test(".readJSON(…) with fallback", async () => {
|
|
|
508
515
|
);
|
|
509
516
|
});
|
|
510
517
|
|
|
511
|
-
test(".write(…)", async () => {
|
|
518
|
+
test.concurrent(".write(…)", async () => {
|
|
512
519
|
const tempDir = await Path.makeTempDir();
|
|
513
520
|
const file = tempDir.join("file.json");
|
|
514
521
|
expect(await file.write("foo")).toBe(file);
|
|
@@ -524,14 +531,14 @@ test(".write(…)", async () => {
|
|
|
524
531
|
).toEqual("bar");
|
|
525
532
|
});
|
|
526
533
|
|
|
527
|
-
test(".writeJSON(…)", async () => {
|
|
534
|
+
test.concurrent(".writeJSON(…)", async () => {
|
|
528
535
|
const file = (await Path.makeTempDir()).join("file.json");
|
|
529
536
|
expect(await file.writeJSON({ foo: "bar" })).toBe(file);
|
|
530
537
|
|
|
531
538
|
expect(await file.readJSON()).toEqual<Record<string, string>>({ foo: "bar" });
|
|
532
539
|
});
|
|
533
540
|
|
|
534
|
-
test(".appendFile(…)", async () => {
|
|
541
|
+
test.concurrent(".appendFile(…)", async () => {
|
|
535
542
|
const file = (await Path.makeTempDir()).join("file.txt");
|
|
536
543
|
await file.appendFile("test\n");
|
|
537
544
|
expect(await file.readText()).toEqual("test\n");
|
|
@@ -539,7 +546,7 @@ test(".appendFile(…)", async () => {
|
|
|
539
546
|
expect(await file.readText()).toEqual("test\nmore\n");
|
|
540
547
|
});
|
|
541
548
|
|
|
542
|
-
test(".readDir(…)", async () => {
|
|
549
|
+
test.concurrent(".readDir(…)", async () => {
|
|
543
550
|
const dir = await Path.makeTempDir();
|
|
544
551
|
await dir.join("file.txt").write("hello");
|
|
545
552
|
await dir.join("dir/file.json").write("hello");
|
|
@@ -553,7 +560,7 @@ test(".readDir(…)", async () => {
|
|
|
553
560
|
);
|
|
554
561
|
});
|
|
555
562
|
|
|
556
|
-
test(".symlink(…)", async () => {
|
|
563
|
+
test.concurrent(".symlink(…)", async () => {
|
|
557
564
|
const tempDir = await Path.makeTempDir();
|
|
558
565
|
const source = tempDir.join("foo.txt");
|
|
559
566
|
const target = tempDir.join("bar.txt");
|
|
@@ -565,7 +572,7 @@ test(".symlink(…)", async () => {
|
|
|
565
572
|
expect(await target.readText()).toEqual("hello");
|
|
566
573
|
});
|
|
567
574
|
|
|
568
|
-
test(".realpath(…)", async () => {
|
|
575
|
+
test.concurrent(".realpath(…)", async () => {
|
|
569
576
|
const tempDir = await Path.makeTempDir();
|
|
570
577
|
const source = tempDir.join("foo.txt");
|
|
571
578
|
await source.write("hello world!");
|
|
@@ -576,7 +583,7 @@ test(".realpath(…)", async () => {
|
|
|
576
583
|
);
|
|
577
584
|
});
|
|
578
585
|
|
|
579
|
-
test(".stat(…)", async () => {
|
|
586
|
+
test.concurrent(".stat(…)", async () => {
|
|
580
587
|
const file = (await Path.makeTempDir()).join("foo.txt");
|
|
581
588
|
await file.write("hello");
|
|
582
589
|
|
|
@@ -585,7 +592,7 @@ test(".stat(…)", async () => {
|
|
|
585
592
|
expect((await file.stat({ bigint: true })).size).toBeTypeOf("bigint");
|
|
586
593
|
});
|
|
587
594
|
|
|
588
|
-
test(".lstat(…)", async () => {
|
|
595
|
+
test.concurrent(".lstat(…)", async () => {
|
|
589
596
|
const tempDir = await Path.makeTempDir();
|
|
590
597
|
const source = tempDir.join("foo.txt");
|
|
591
598
|
const target = tempDir.join("bar.txt");
|
|
@@ -598,7 +605,7 @@ test(".lstat(…)", async () => {
|
|
|
598
605
|
expect(await target.readText()).toEqual("hello");
|
|
599
606
|
});
|
|
600
607
|
|
|
601
|
-
test(".chmod(…)", async () => {
|
|
608
|
+
test.concurrent(".chmod(…)", async () => {
|
|
602
609
|
const binPath = (await Path.makeTempDir()).join("nonexistent.bin");
|
|
603
610
|
expect(() => new PrintableShellCommand(binPath, []).text()).toThrow(
|
|
604
611
|
/ENOENT|Premature close/,
|
|
@@ -617,7 +624,7 @@ echo hi`);
|
|
|
617
624
|
expect(await new PrintableShellCommand(binPath, []).text()).toEqual("hi\n");
|
|
618
625
|
});
|
|
619
626
|
|
|
620
|
-
test(".chmodX(…)", async () => {
|
|
627
|
+
test.concurrent(".chmodX(…)", async () => {
|
|
621
628
|
const binPath = (await Path.makeTempDir()).join("nonexistent.bin");
|
|
622
629
|
expect(() => new PrintableShellCommand(binPath, []).text()).toThrow(
|
|
623
630
|
/ENOENT|Premature close/,
|
|
@@ -632,22 +639,28 @@ echo hi`);
|
|
|
632
639
|
expect(() => new PrintableShellCommand(binPath, []).text()).toThrow(
|
|
633
640
|
/EACCES|Premature close/,
|
|
634
641
|
);
|
|
642
|
+
expect((await binPath.stat()).mode & constants.S_IWUSR).toBeTruthy();
|
|
643
|
+
await binPath.chmod(0o444);
|
|
644
|
+
expect((await binPath.stat()).mode & constants.S_IWUSR).toBeFalsy();
|
|
645
|
+
expect((await binPath.stat()).mode & constants.S_IXUSR).toBeFalsy();
|
|
635
646
|
await binPath.chmodX();
|
|
636
647
|
expect(await new PrintableShellCommand(binPath, []).text()).toEqual("hi\n");
|
|
648
|
+
expect((await binPath.stat()).mode & constants.S_IWUSR).toBeFalsy();
|
|
649
|
+
expect((await binPath.stat()).mode & constants.S_IXUSR).toBeTruthy();
|
|
637
650
|
});
|
|
638
651
|
|
|
639
|
-
test(".homedir", async () => {
|
|
652
|
+
test.concurrent(".homedir", async () => {
|
|
640
653
|
expect(Path.homedir.path).toEqual("/mock/home/dir");
|
|
641
654
|
});
|
|
642
655
|
|
|
643
|
-
test(".cwd", async () => {
|
|
656
|
+
test.concurrent(".cwd", async () => {
|
|
644
657
|
expect(Path.cwd.basename.path).toEqual("path-class");
|
|
645
658
|
const tempDir = await Path.makeTempDir();
|
|
646
659
|
chdir(tempDir.path);
|
|
647
660
|
expect(await realpath(Path.cwd.path)).toEqual(await realpath(tempDir.path));
|
|
648
661
|
});
|
|
649
662
|
|
|
650
|
-
test(".xdg", async () => {
|
|
663
|
+
test.concurrent(".xdg", async () => {
|
|
651
664
|
expect(Path.xdg.cache.path).toEqual("/mock/home/dir/.cache");
|
|
652
665
|
expect(Path.xdg.config.path).toEqual("/xdg/config");
|
|
653
666
|
expect(Path.xdg.data.path).toEqual("/mock/home/dir/.local/share");
|
|
@@ -661,6 +674,7 @@ test(".xdg", async () => {
|
|
|
661
674
|
const spy = spyOn(console, "log");
|
|
662
675
|
|
|
663
676
|
test(".debugPrint(…)", async () => {
|
|
677
|
+
spy.mockReset();
|
|
664
678
|
Path.homedir.debugPrint("Here is a test log of the mock home directory:");
|
|
665
679
|
expect(spy.mock.calls).toEqual([
|
|
666
680
|
["Here is a test log of the mock home directory:"],
|
|
@@ -669,6 +683,7 @@ test(".debugPrint(…)", async () => {
|
|
|
669
683
|
});
|
|
670
684
|
|
|
671
685
|
test(".stringifyIfPath(…)", async () => {
|
|
686
|
+
spy.mockReset();
|
|
672
687
|
expect(stringifyIfPath(Path.homedir)).toBe("/mock/home/dir");
|
|
673
688
|
expect(stringifyIfPath("/mock/home/dir")).toBe("/mock/home/dir");
|
|
674
689
|
expect(stringifyIfPath(4)).toBe(4);
|
package/src/Path.ts
CHANGED
|
@@ -209,6 +209,19 @@ export class Path {
|
|
|
209
209
|
return this.#path;
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Format this with the escape codes for printing to the shell in bold blue.
|
|
214
|
+
*
|
|
215
|
+
* Example usage:
|
|
216
|
+
*
|
|
217
|
+
* console.log(`Processing: ${path.blue}`)
|
|
218
|
+
*
|
|
219
|
+
*/
|
|
220
|
+
get blue() {
|
|
221
|
+
const { styleText } = globalThis.process.getBuiltinModule("node:util");
|
|
222
|
+
return styleText(["bold", "blue"], this.#path);
|
|
223
|
+
}
|
|
224
|
+
|
|
212
225
|
/** Constructs a new path by appending the given path segments.
|
|
213
226
|
* This follows `node` semantics for absolute paths: leading slashes in the given descendant segments are ignored.
|
|
214
227
|
*/
|
|
@@ -589,7 +602,7 @@ export class Path {
|
|
|
589
602
|
return targetPath;
|
|
590
603
|
}
|
|
591
604
|
|
|
592
|
-
// I don't think `
|
|
605
|
+
// I don't think `realpath` is a great name, but it does match the
|
|
593
606
|
// well-established canonical commandline name. So in this case we keep the
|
|
594
607
|
// name instead of using `realPath`.
|
|
595
608
|
//
|
|
@@ -620,11 +633,7 @@ export class Path {
|
|
|
620
633
|
async chmodX(): Promise<Path> {
|
|
621
634
|
const { mode } = await this.stat();
|
|
622
635
|
await this.chmod(
|
|
623
|
-
mode |
|
|
624
|
-
constants.S_IRWXU |
|
|
625
|
-
constants.S_IXUSR |
|
|
626
|
-
constants.S_IXGRP |
|
|
627
|
-
constants.S_IXOTH,
|
|
636
|
+
mode | constants.S_IXUSR | constants.S_IXGRP | constants.S_IXOTH,
|
|
628
637
|
);
|
|
629
638
|
return this;
|
|
630
639
|
}
|
|
@@ -2,11 +2,11 @@ import { expect, test } from "bun:test";
|
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import "./PathSync";
|
|
5
|
+
import { constants } from "node:fs/promises";
|
|
5
6
|
import { PrintableShellCommand } from "printable-shell-command";
|
|
6
|
-
|
|
7
7
|
import { PathSync } from "./PathSync";
|
|
8
8
|
|
|
9
|
-
test(".existsAsFileSync()", () => {
|
|
9
|
+
test.concurrent(".existsAsFileSync()", () => {
|
|
10
10
|
const filePath = PathSync.makeTempDirSync().join("file.txt");
|
|
11
11
|
expect(filePath.existsSync()).toBe(false);
|
|
12
12
|
expect(filePath.existsSync({ mustBe: "file" })).toBe(false);
|
|
@@ -24,7 +24,7 @@ test(".existsAsFileSync()", () => {
|
|
|
24
24
|
expect(filePath.existsAsFileSync()).toBe(true);
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
test(".existsAsDir()", () => {
|
|
27
|
+
test.concurrent(".existsAsDir()", () => {
|
|
28
28
|
const filePath = PathSync.makeTempDirSync();
|
|
29
29
|
expect(filePath.existsSync()).toBe(true);
|
|
30
30
|
expect(() => filePath.existsSync({ mustBe: "file" })).toThrow(
|
|
@@ -39,14 +39,14 @@ test(".existsAsDir()", () => {
|
|
|
39
39
|
expect(filePath.existsAsDirSync()).toBe(false);
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
-
test(".mkdirSync(…) (un-nested)", () => {
|
|
42
|
+
test.concurrent(".mkdirSync(…) (un-nested)", () => {
|
|
43
43
|
const dir = PathSync.makeTempDirSync().join("mkdir-test");
|
|
44
44
|
expect(dir.existsSync()).toBe(false);
|
|
45
45
|
dir.mkdirSync();
|
|
46
46
|
expect(dir.existsSync()).toBe(true);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
test(".mkdirSync(…) (nested)", () => {
|
|
49
|
+
test.concurrent(".mkdirSync(…) (nested)", () => {
|
|
50
50
|
const dir = PathSync.makeTempDirSync().join("mkdir-test/nested");
|
|
51
51
|
expect(dir.existsSync()).toBe(false);
|
|
52
52
|
expect(() => dir.mkdirSync({ recursive: false })).toThrow("no such file");
|
|
@@ -54,7 +54,7 @@ test(".mkdirSync(…) (nested)", () => {
|
|
|
54
54
|
expect(dir.existsSync()).toBe(true);
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
-
test(".cpSync(…)", () => {
|
|
57
|
+
test.concurrent(".cpSync(…)", () => {
|
|
58
58
|
const parentDir = PathSync.makeTempDirSync();
|
|
59
59
|
const file1 = parentDir.join("file1.txt");
|
|
60
60
|
const file2 = parentDir.join("file2.txt");
|
|
@@ -68,7 +68,7 @@ test(".cpSync(…)", () => {
|
|
|
68
68
|
expect(file2.existsSync()).toBe(true);
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
test(".renameSync(…)", () => {
|
|
71
|
+
test.concurrent(".renameSync(…)", () => {
|
|
72
72
|
const parentDir = PathSync.makeTempDirSync();
|
|
73
73
|
const file1 = parentDir.join("file1.txt");
|
|
74
74
|
const file2 = parentDir.join("file2.txt");
|
|
@@ -82,7 +82,7 @@ test(".renameSync(…)", () => {
|
|
|
82
82
|
expect(file2.existsSync()).toBe(true);
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
-
test(".makeTempDirSync(…)", () => {
|
|
85
|
+
test.concurrent(".makeTempDirSync(…)", () => {
|
|
86
86
|
const tempDir = PathSync.makeTempDirSync();
|
|
87
87
|
expect(tempDir.path).toContain("/js-temp-");
|
|
88
88
|
expect(tempDir.basename.path).toStartWith("js-temp-");
|
|
@@ -93,7 +93,7 @@ test(".makeTempDirSync(…)", () => {
|
|
|
93
93
|
expect(tempDir2.basename.path).toStartWith("foo");
|
|
94
94
|
});
|
|
95
95
|
|
|
96
|
-
test(".rmSync(…) (file)", () => {
|
|
96
|
+
test.concurrent(".rmSync(…) (file)", () => {
|
|
97
97
|
const file = PathSync.makeTempDirSync().join("file.txt");
|
|
98
98
|
file.writeSync("");
|
|
99
99
|
expect(file.existsAsFileSync()).toBe(true);
|
|
@@ -103,7 +103,7 @@ test(".rmSync(…) (file)", () => {
|
|
|
103
103
|
expect(() => file.rmSync()).toThrowError(/ENOENT/);
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
test(".rmSync(…) (folder)", () => {
|
|
106
|
+
test.concurrent(".rmSync(…) (folder)", () => {
|
|
107
107
|
const tempDir = PathSync.makeTempDirSync();
|
|
108
108
|
const file = tempDir.join("file.txt");
|
|
109
109
|
file.writeSync("");
|
|
@@ -115,7 +115,7 @@ test(".rmSync(…) (folder)", () => {
|
|
|
115
115
|
expect(() => tempDir.rmSync()).toThrowError(/ENOENT/);
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
-
test(".rmDirSync(…) (folder)", () => {
|
|
118
|
+
test.concurrent(".rmDirSync(…) (folder)", () => {
|
|
119
119
|
const tempDir = PathSync.makeTempDirSync();
|
|
120
120
|
const file = tempDir.join("file.txt");
|
|
121
121
|
file.writeSync("");
|
|
@@ -127,7 +127,7 @@ test(".rmDirSync(…) (folder)", () => {
|
|
|
127
127
|
expect(() => tempDir.rmDirSync()).toThrowError(/ENOENT/);
|
|
128
128
|
});
|
|
129
129
|
|
|
130
|
-
test(".rm_rfSync(…) (file)", () => {
|
|
130
|
+
test.concurrent(".rm_rfSync(…) (file)", () => {
|
|
131
131
|
const file = PathSync.makeTempDirSync().join("file.txt");
|
|
132
132
|
file.writeSync("");
|
|
133
133
|
expect(file.existsAsFileSync()).toBe(true);
|
|
@@ -138,7 +138,7 @@ test(".rm_rfSync(…) (file)", () => {
|
|
|
138
138
|
expect(file.existsAsFileSync()).toBe(false);
|
|
139
139
|
});
|
|
140
140
|
|
|
141
|
-
test(".rm_rfSync(…) (folder)", () => {
|
|
141
|
+
test.concurrent(".rm_rfSync(…) (folder)", () => {
|
|
142
142
|
const tempDir = PathSync.makeTempDirSync();
|
|
143
143
|
tempDir.join("file.txt").writeSync("");
|
|
144
144
|
expect(tempDir.path).toContain("/js-temp-");
|
|
@@ -149,7 +149,7 @@ test(".rm_rfSync(…) (folder)", () => {
|
|
|
149
149
|
expect(tempDir.existsSync()).toBe(false);
|
|
150
150
|
});
|
|
151
151
|
|
|
152
|
-
test(".readTextSync()", () => {
|
|
152
|
+
test.concurrent(".readTextSync()", () => {
|
|
153
153
|
const file = PathSync.makeTempDirSync().join("file.txt");
|
|
154
154
|
file.writeSync("hi");
|
|
155
155
|
file.writeSync("bye");
|
|
@@ -158,7 +158,7 @@ test(".readTextSync()", () => {
|
|
|
158
158
|
expect(readFileSync(file.path, "utf-8")).toBe("bye");
|
|
159
159
|
});
|
|
160
160
|
|
|
161
|
-
test(".readJSONSync()", () => {
|
|
161
|
+
test.concurrent(".readJSONSync()", () => {
|
|
162
162
|
const file = PathSync.makeTempDirSync().join("file.json");
|
|
163
163
|
file.writeSync(JSON.stringify({ foo: "bar" }));
|
|
164
164
|
|
|
@@ -169,7 +169,7 @@ test(".readJSONSync()", () => {
|
|
|
169
169
|
>({ foo: "bar" });
|
|
170
170
|
});
|
|
171
171
|
|
|
172
|
-
test(".readJSONSync(…) with fallback", () => {
|
|
172
|
+
test.concurrent(".readJSONSync(…) with fallback", () => {
|
|
173
173
|
const tempDir = PathSync.makeTempDirSync();
|
|
174
174
|
const file = tempDir.join("file.json");
|
|
175
175
|
const json: { foo?: number } = file.readJSONSync({ fallback: { foo: 4 } });
|
|
@@ -187,7 +187,7 @@ test(".readJSONSync(…) with fallback", () => {
|
|
|
187
187
|
);
|
|
188
188
|
});
|
|
189
189
|
|
|
190
|
-
test(".writeSync(…)", () => {
|
|
190
|
+
test.concurrent(".writeSync(…)", () => {
|
|
191
191
|
const tempDir = PathSync.makeTempDirSync();
|
|
192
192
|
const file = tempDir.join("file.json");
|
|
193
193
|
expect(file.writeSync("foo")).toBe(file);
|
|
@@ -203,14 +203,14 @@ test(".writeSync(…)", () => {
|
|
|
203
203
|
).toEqual("bar");
|
|
204
204
|
});
|
|
205
205
|
|
|
206
|
-
test(".writeJSONSync(…)", () => {
|
|
206
|
+
test.concurrent(".writeJSONSync(…)", () => {
|
|
207
207
|
const file = PathSync.makeTempDirSync().join("file.json");
|
|
208
208
|
expect(file.writeJSONSync({ foo: "bar" })).toBe(file);
|
|
209
209
|
|
|
210
210
|
expect(file.readJSONSync()).toEqual<Record<string, string>>({ foo: "bar" });
|
|
211
211
|
});
|
|
212
212
|
|
|
213
|
-
test(".appendFileSync(…)", () => {
|
|
213
|
+
test.concurrent(".appendFileSync(…)", () => {
|
|
214
214
|
const file = PathSync.makeTempDirSync().join("file.txt");
|
|
215
215
|
file.appendFileSync("test\n");
|
|
216
216
|
expect(file.readTextSync()).toEqual("test\n");
|
|
@@ -218,7 +218,7 @@ test(".appendFileSync(…)", () => {
|
|
|
218
218
|
expect(file.readTextSync()).toEqual("test\nmore\n");
|
|
219
219
|
});
|
|
220
220
|
|
|
221
|
-
test(".readDirSync(…)", () => {
|
|
221
|
+
test.concurrent(".readDirSync(…)", () => {
|
|
222
222
|
const dir = PathSync.makeTempDirSync();
|
|
223
223
|
dir.join("file.txt").writeSync("hello");
|
|
224
224
|
dir.join("dir/file.json").writeSync("hello");
|
|
@@ -232,7 +232,7 @@ test(".readDirSync(…)", () => {
|
|
|
232
232
|
);
|
|
233
233
|
});
|
|
234
234
|
|
|
235
|
-
test(".symlinkSync(…)", () => {
|
|
235
|
+
test.concurrent(".symlinkSync(…)", () => {
|
|
236
236
|
const tempDir = PathSync.makeTempDirSync();
|
|
237
237
|
const source = tempDir.join("foo.txt");
|
|
238
238
|
const target = tempDir.join("bar.txt");
|
|
@@ -244,7 +244,7 @@ test(".symlinkSync(…)", () => {
|
|
|
244
244
|
expect(target.readTextSync()).toEqual("hello");
|
|
245
245
|
});
|
|
246
246
|
|
|
247
|
-
test(".realpathSync(…)", () => {
|
|
247
|
+
test.concurrent(".realpathSync(…)", () => {
|
|
248
248
|
const tempDir = PathSync.makeTempDirSync();
|
|
249
249
|
const source = tempDir.join("foo.txt");
|
|
250
250
|
source.writeSync("hello world!");
|
|
@@ -253,7 +253,7 @@ test(".realpathSync(…)", () => {
|
|
|
253
253
|
expect(source.realpathSync().path).toEqual(target.realpathSync().path);
|
|
254
254
|
});
|
|
255
255
|
|
|
256
|
-
test(".statSync(…)", () => {
|
|
256
|
+
test.concurrent(".statSync(…)", () => {
|
|
257
257
|
const file = PathSync.makeTempDirSync().join("foo.txt");
|
|
258
258
|
file.writeSync("hello");
|
|
259
259
|
|
|
@@ -262,7 +262,7 @@ test(".statSync(…)", () => {
|
|
|
262
262
|
expect(file.statSync({ bigint: true })?.size).toBeTypeOf("bigint");
|
|
263
263
|
});
|
|
264
264
|
|
|
265
|
-
test(".lstatSync(…)", () => {
|
|
265
|
+
test.concurrent(".lstatSync(…)", () => {
|
|
266
266
|
const tempDir = PathSync.makeTempDirSync();
|
|
267
267
|
const source = tempDir.join("foo.txt");
|
|
268
268
|
const target = tempDir.join("bar.txt");
|
|
@@ -275,7 +275,7 @@ test(".lstatSync(…)", () => {
|
|
|
275
275
|
expect(target.readTextSync()).toEqual("hello");
|
|
276
276
|
});
|
|
277
277
|
|
|
278
|
-
test(".chmodSync(…)", () => {
|
|
278
|
+
test.concurrent(".chmodSync(…)", () => {
|
|
279
279
|
const binPath = PathSync.makeTempDirSync().join("nonexistent.bin");
|
|
280
280
|
expect(() => new PrintableShellCommand(binPath, []).text()).toThrow(
|
|
281
281
|
/ENOENT|Premature close/,
|
|
@@ -294,7 +294,7 @@ echo hi`);
|
|
|
294
294
|
expect(() => new PrintableShellCommand(binPath, []).text()).not.toThrow();
|
|
295
295
|
});
|
|
296
296
|
|
|
297
|
-
test(".chmodXSync(…)", () => {
|
|
297
|
+
test.concurrent(".chmodXSync(…)", () => {
|
|
298
298
|
const binPath = PathSync.makeTempDirSync().join("nonexistent.bin");
|
|
299
299
|
expect(() => new PrintableShellCommand(binPath, []).text()).toThrow(
|
|
300
300
|
/ENOENT|Premature close/,
|
|
@@ -309,6 +309,12 @@ echo hi`);
|
|
|
309
309
|
expect(() => new PrintableShellCommand(binPath, []).text()).toThrow(
|
|
310
310
|
/EACCES|Premature close/,
|
|
311
311
|
);
|
|
312
|
+
expect(binPath.statSync().mode & constants.S_IWUSR).toBeTruthy();
|
|
313
|
+
binPath.chmodSync(0o444);
|
|
314
|
+
expect(binPath.statSync().mode & constants.S_IWUSR).toBeFalsy();
|
|
315
|
+
expect(binPath.statSync().mode & constants.S_IXUSR).toBeFalsy();
|
|
312
316
|
binPath.chmodXSync();
|
|
313
317
|
expect(() => new PrintableShellCommand(binPath, []).text()).not.toThrow();
|
|
318
|
+
expect(binPath.statSync().mode & constants.S_IWUSR).toBeFalsy();
|
|
319
|
+
expect(binPath.statSync().mode & constants.S_IXUSR).toBeTruthy();
|
|
314
320
|
});
|
package/src/sync/PathSync.ts
CHANGED
|
@@ -260,11 +260,7 @@ export class PathSync extends Path {
|
|
|
260
260
|
chmodXSync(): PathSync {
|
|
261
261
|
const { mode } = this.statSync();
|
|
262
262
|
this.chmodSync(
|
|
263
|
-
mode |
|
|
264
|
-
constants.S_IRWXU |
|
|
265
|
-
constants.S_IXUSR |
|
|
266
|
-
constants.S_IXGRP |
|
|
267
|
-
constants.S_IXOTH,
|
|
263
|
+
mode | constants.S_IXUSR | constants.S_IXGRP | constants.S_IXOTH,
|
|
268
264
|
);
|
|
269
265
|
return this;
|
|
270
266
|
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/Path.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n appendFile,\n chmod,\n constants,\n cp,\n lstat,\n mkdir,\n mkdtemp,\n readdir,\n readFile,\n realpath,\n rename,\n rm,\n rmdir,\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 { cwd } from \"node:process\";\nimport { Readable } from \"node:stream\";\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\ntype WritableData = Parameters<typeof writeFile>[1] | ReadableStream | Response;\nasync function wrangleWritableData(\n data: WritableData | Promise<WritableData>,\n): Promise<Parameters<typeof writeFile>[1]> {\n data = await data;\n if (data instanceof Response) {\n data = data.body ? Readable.fromWeb(data.body) : new Uint8Array(0);\n }\n if (data instanceof ReadableStream) {\n data = Readable.fromWeb(data);\n }\n return data;\n}\n\nexport enum ResolutionPrefix {\n Absolute = \"absolute\",\n Relative = \"relative\",\n Bare = \"bare\",\n}\n\nexport function resolutionPrefix(pathString: string): ResolutionPrefix {\n if (pathString.startsWith(\"/\")) {\n return ResolutionPrefix.Absolute;\n } else if (pathString.startsWith(\"./\")) {\n return ResolutionPrefix.Relative;\n } else if (pathString.startsWith(\"../\")) {\n return ResolutionPrefix.Relative;\n } else if (pathString === \".\") {\n return ResolutionPrefix.Relative;\n } else if (pathString === \"..\") {\n return ResolutionPrefix.Relative;\n }\n return ResolutionPrefix.Bare;\n}\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 const s = Path.#pathlikeToString(path);\n this.#setNormalizedPath(s);\n }\n\n static fromString(s: string): Path {\n if (typeof s !== \"string\") {\n throw new Error(\n \"Invalid argument to `Path.fromString(\u2026)` \u2014 expected a string.\",\n );\n }\n return new Path(s);\n }\n\n get resolutionPrefix(): ResolutionPrefix {\n return resolutionPrefix(this.#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 if (typeof base === \"string\" && !base.startsWith(\"file://\")) {\n return pathToFileURL(base);\n }\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 // Preserves the `ResolutionPrefix` status when possible.\n #setNormalizedPath(path: string): void {\n const prefix = resolutionPrefix(path);\n this.#path = join(path);\n if (prefix === ResolutionPrefix.Relative && !this.#path.startsWith(\".\")) {\n // We don't have to handle the case of `\".\"`, as it already starts with `\".\"`\n this.#path = `./${this.#path}`;\n }\n }\n\n isAbsolutePath(): boolean {\n return this.resolutionPrefix === ResolutionPrefix.Absolute;\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 * Toggles or sets a trailing slash as specified.\n * If the path is `/`, it will always be left as-is.\n */\n // Similar convention to:\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle Most\n // use cases will probably use the `force` parameters, but supporting the\n // \"toggle\" use case is easy to implement and hopefully will make the name\n // and API more familiar to web devs.\n toggleTrailingSlash(force?: boolean): Path {\n if (this.#path === \"/\") {\n return this;\n }\n const wantTrailingSlash = force ?? !this.hasTrailingSlash();\n if (wantTrailingSlash) {\n return this.hasTrailingSlash() ? this : this.join(\"./\");\n } else {\n return this.hasTrailingSlash() ? new Path(this.#path.slice(0, -1)) : this;\n }\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 const s = stringifyIfPath(segment);\n if (resolutionPrefix(s) === ResolutionPrefix.Absolute) {\n throw new Error(\n \"Arguments to `.join(\u2026)` cannot be absolute. Use `.asRelative()` to convert them first if needed.\",\n );\n }\n return s;\n });\n return new Path(join(this.#path, ...segmentStrings));\n }\n\n /**\n * Adjust the prefix to construct a relative path.\n *\n * | Example input | Output |\n * |-----------------|-----------------|\n * | `\"bare\"` | `\"./bare\"` |\n * | `\"./relative\"` | `\"./relative\"` |\n * | `\"../up-first\"` | `\"../up-first\"` |\n * | `\"/absolute\"` | `\"./absolute\"` |\n *\n */\n asRelative(): Path {\n return new Path(`./${this.#path}`);\n }\n\n /**\n * Adjust the prefix to construct an absolute path.\n *\n * | Example input | Output |\n * |-----------------|---------------|\n * | `\"bare\"` | `\"/bare\"` |\n * | `\"./relative\"` | `\"/relative\"` |\n * | `\"../up-first\"` | `\"/up-first\"` |\n * | `\"/absolute\"` | `\"/absolute\"` |\n *\n */\n asAbsolute(): Path {\n return new Path(join(\"/\", this.#path));\n }\n\n /**\n * Adjust the prefix to construct a bare path. Note that this returns `\".\"` if\n * there are no named paths left.\n *\n * | Example input | Output |\n * |-------------------|--------------|\n * | `\"bare\"` | `\"bare\"` |\n * | `\"./relative\" ` | `\"relative\"` |\n * | `\"/absolute\"` | `\"absolute\"` |\n * | `\".\"` | `\".\"` |\n * | `\"down-first/..\"` | `\".\"` |\n * | `\"../up-first\"` | (error) |\n * | `\"..\"` | (error) |\n *\n * Specify `parentTraversalPrefixHandling` in the `options` if you would like\n * to strip or keep resolution prefixes like `../` rather than erroring.\n *\n * | Example input | Output with `{ parentTraversalPrefixHandling: \"strip\" }` |\n * |----------------------|----------------------------------------------------------|\n * | `\"../up-first\"` | `\"up-first\"` |\n * | `\"..\"` | `\".\"` |\n *\n * | Example input | Output with `{ parentTraversalPrefixHandling: \"keep\" }` |\n * |----------------------|---------------------------------------------------------|\n * | `\"../up-first\"` | `\"../up-first\"` |\n * | `\"..\"` | `\"..\"` |\n *\n * If you need the output to start with a named component and return values\n * like `.`, `..`, `../`, or `../\u2026` are not okay, pass\n * `requireNamedComponentPrefix: true`. This is useful if the path represents\n * an `npm`-style package name (e.g. `\"typescript\"`, `\"@biomejs/biome\"`).\n *\n */\n asBare(options?: {\n parentTraversalPrefixHandling?: \"error\" | \"strip\" | \"keep\";\n requireNamedComponentPrefix?: boolean;\n }): Path {\n const path = new Path(join(\".\", this.#path));\n if (!path.#path.startsWith(\"../\") && path.#path !== \"..\") {\n if (\n options?.requireNamedComponentPrefix &&\n path.resolutionPrefix === ResolutionPrefix.Relative\n ) {\n throw new Error(\"Output does not start with a named component.\");\n }\n return path;\n }\n const parentTraversalHandling =\n options?.parentTraversalPrefixHandling ?? \"error\";\n switch (parentTraversalHandling) {\n case \"error\": {\n throw new Error(\n 'Converting path to a bare path resulted in a `..` traversal prefix. Pass `\"strip\"` or `\"keep\"` as the `parentTraversalHandling` option to avoid an error.',\n );\n }\n case \"strip\": {\n let newPath = path.#path.replace(/^(\\.\\.\\/)+/, \"\");\n if ([\"\", \"..\"].includes(newPath)) {\n newPath = \".\";\n }\n const output = new Path(newPath);\n if (\n options?.requireNamedComponentPrefix &&\n output.resolutionPrefix === ResolutionPrefix.Relative\n ) {\n throw new Error(\"Output does not start with a named component.\");\n }\n return new Path(newPath);\n }\n case \"keep\": {\n if (options?.requireNamedComponentPrefix) {\n throw new Error(\"Output does not start with a named component.\");\n }\n return path;\n }\n }\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 if (constraints?.mustBe === \"file\") {\n mustNotHaveTrailingSlash(this);\n }\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 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 /**\n * Create a temporary dir inside the global temp dir for the current user.\n *\n * This can be used with [`await\n * using`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/await_using)\n * to automatically delete the dir when it goes out of scope.\n *\n * {\n * await using tempDir = await Path.makeTempDir();\n * // Temporary dir exists while we're inside this block.\n * }\n * // Temporary dir has now been deleted.\n *\n * Note that (due to the semantics of JS runtime implementations) this does\n * not delete the temp dir if the process calls `exit(\u2026)` before the `using`\n * goes out of scope.\n *\n * */\n static async makeTempDir(prefix?: string): Promise<AsyncDisposablePath> {\n return new AsyncDisposablePath(\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 async rmDir(): Promise<void> {\n await rmdir(this.#path);\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 /**\n * Reads JSON from the given file and parses it. No validation is performed\n * (beyond JSON parsing).\n *\n * An optional `fallback` value can be specified. It will be used if (and only\n * if) the file does not exist.\n *\n */\n\n // biome-ignore lint/suspicious/noExplicitAny: Allow a default of `any` to match `JSON.parse(\u2026)`.\n async readJSON<T = any>(options?: { fallback?: T }): Promise<T> {\n try {\n return JSON.parse(await this.readText());\n } catch (e) {\n if (\n (e as { code?: string }).code === \"ENOENT\" &&\n options &&\n \"fallback\" in options\n ) {\n return options.fallback as T;\n }\n throw e;\n }\n }\n\n /**\n * Returns the original `Path` (for chaining).\n */\n async appendFile(\n data: Parameters<typeof appendFile>[1],\n options?: Parameters<typeof appendFile>[2],\n ): Promise<Path> {\n await appendFile(this.#path, data, options);\n return this;\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: WritableData | Promise<WritableData>,\n options?: Parameters<typeof writeFile>[2],\n ): Promise<Path> {\n await this.parent.mkdir();\n await writeFile(this.#path, await wrangleWritableData(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 // I don't think `lstat` is a great name, but it does match the\n // well-established canonical commandline name. So in this case we keep the\n // name instead of using `realPath`.\n //\n // Note: There are no options in our API, because the only option is an\n // encoding. We set the encoding to construct the returned `Path`.\n async realpath(): Promise<Path> {\n return new Path(await realpath(this.#path, \"utf-8\"));\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 async chmod(mode: Parameters<typeof chmod>[1]): Promise<Path> {\n await chmod(this.#path, mode);\n return this;\n }\n\n /**\n * Add the executable bit (for everyone) to the given path without modifying other bits (`chmod +x`).\n */\n async chmodX(): Promise<Path> {\n const { mode } = await this.stat();\n await this.chmod(\n mode |\n constants.S_IRWXU |\n constants.S_IXUSR |\n constants.S_IXGRP |\n constants.S_IXOTH,\n );\n return this;\n }\n\n static get homedir(): Path {\n return new Path(homedir());\n }\n\n /**\n * Get the current working directory as a path. Always includes a trailing slash.\n * Note that this computes the `cwd` from fresh every time, in case it has changed for the current process.\n */\n static get cwd(): Path {\n return new Path(cwd()).toggleTrailingSlash(true);\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\nexport class AsyncDisposablePath extends Path {\n async [Symbol.asyncDispose]() {\n await this.rm_rf();\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": ["ResolutionPrefix"]
|
|
7
|
-
}
|