path-class 0.1.0 → 0.3.0
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/index.d.ts +51 -0
- package/dist/lib/path-class/index.js +193 -0
- package/dist/lib/path-class/index.js.map +7 -0
- package/package.json +21 -4
- package/src/index.test.ts +195 -0
- package/src/index.ts +103 -13
- package/src/test.preload.ts +19 -0
- package/.github/workflows/publish-github-release.yaml +0 -13
- package/Makefile +0 -11
- package/biome.json +0 -7
- package/bun.lock +0 -219
- package/tsconfig.json +0 -3
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { cp, mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
export declare class Path {
|
|
3
|
+
#private;
|
|
4
|
+
constructor(path: string | URL | Path);
|
|
5
|
+
toString(): string;
|
|
6
|
+
join(...segments: string[]): Path;
|
|
7
|
+
extendBasename(suffix: string): Path;
|
|
8
|
+
get parent(): Path;
|
|
9
|
+
/** @deprecated Alias for `.parent`. */
|
|
10
|
+
get dirname(): Path;
|
|
11
|
+
get basename(): Path;
|
|
12
|
+
get extension(): string;
|
|
13
|
+
/** @deprecated Alias for `.extension`. */
|
|
14
|
+
get extname(): string;
|
|
15
|
+
exists(constraints?: {
|
|
16
|
+
mustBe: "file" | "directory";
|
|
17
|
+
}): Promise<boolean>;
|
|
18
|
+
existsAsFile(): Promise<boolean>;
|
|
19
|
+
existsAsDir(): Promise<boolean>;
|
|
20
|
+
/** Defaults to `recursive: true`. */
|
|
21
|
+
mkdir(options?: Parameters<typeof mkdir>[1]): Promise<Path>;
|
|
22
|
+
/** Returns the destination path. */
|
|
23
|
+
cp(destination: string | URL | Path, options?: Parameters<typeof cp>[2]): Promise<Path>;
|
|
24
|
+
rename(destination: string | URL | Path): Promise<void>;
|
|
25
|
+
/** Create a temporary dir inside the global temp dir for the current user. */
|
|
26
|
+
static makeTempDir(prefix?: string): Promise<Path>;
|
|
27
|
+
trash(): Promise<void>;
|
|
28
|
+
fileText(): Promise<string>;
|
|
29
|
+
fileJSON<T>(): Promise<T>;
|
|
30
|
+
/** Returns the original `Path` (for chaining). */
|
|
31
|
+
write(data: Parameters<typeof writeFile>[1], options?: Parameters<typeof writeFile>[2]): Promise<Path>;
|
|
32
|
+
/**
|
|
33
|
+
* If only `data` is provided, this is equivalent to:
|
|
34
|
+
*
|
|
35
|
+
* .write(JSON.stringify(data, null, " "));
|
|
36
|
+
*
|
|
37
|
+
* `replacer` and `space` can also be specified, making this equivalent to:
|
|
38
|
+
*
|
|
39
|
+
* .write(JSON.stringify(data, replacer, space));
|
|
40
|
+
*
|
|
41
|
+
* Returns the original `Path` (for chaining).
|
|
42
|
+
*/
|
|
43
|
+
writeJSON<T>(data: T, replacer?: Parameters<typeof JSON.stringify>[1], space?: Parameters<typeof JSON.stringify>[2]): Promise<Path>;
|
|
44
|
+
static get homedir(): Path;
|
|
45
|
+
static xdg: {
|
|
46
|
+
cache: Path;
|
|
47
|
+
config: Path;
|
|
48
|
+
data: Path;
|
|
49
|
+
state: Path;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import {
|
|
3
|
+
cp,
|
|
4
|
+
mkdir,
|
|
5
|
+
mkdtemp,
|
|
6
|
+
readFile,
|
|
7
|
+
rename,
|
|
8
|
+
stat,
|
|
9
|
+
writeFile
|
|
10
|
+
} from "node:fs/promises";
|
|
11
|
+
import { homedir, tmpdir } from "node:os";
|
|
12
|
+
import { basename, dirname, extname, join } from "node:path";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
14
|
+
import { default as trash } from "trash";
|
|
15
|
+
import { xdgCache, xdgConfig, xdgData, xdgState } from "xdg-basedir";
|
|
16
|
+
var Path = class _Path {
|
|
17
|
+
// @ts-expect-error ts(2564): False positive. https://github.com/microsoft/TypeScript/issues/32194
|
|
18
|
+
#path;
|
|
19
|
+
constructor(path) {
|
|
20
|
+
if (path instanceof _Path) {
|
|
21
|
+
this.#setNormalizedPath(path.#path);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (path instanceof URL) {
|
|
25
|
+
this.#setNormalizedPath(fileURLToPath(path));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (typeof path === "string") {
|
|
29
|
+
this.#setNormalizedPath(path);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
throw new Error("Invalid path");
|
|
33
|
+
}
|
|
34
|
+
#setNormalizedPath(path) {
|
|
35
|
+
this.#path = join(path);
|
|
36
|
+
}
|
|
37
|
+
toString() {
|
|
38
|
+
return this.#path;
|
|
39
|
+
}
|
|
40
|
+
/// Constructs a new path by appending the given path segments.
|
|
41
|
+
// TODO: accept `Path` inputs?
|
|
42
|
+
join(...segments) {
|
|
43
|
+
return new _Path(join(this.#path, ...segments));
|
|
44
|
+
}
|
|
45
|
+
extendBasename(suffix) {
|
|
46
|
+
const joinedSuffix = join(suffix);
|
|
47
|
+
if (joinedSuffix !== basename(joinedSuffix)) {
|
|
48
|
+
throw new Error("Invalid suffix to extend file name.");
|
|
49
|
+
}
|
|
50
|
+
return new _Path(this.#path + joinedSuffix);
|
|
51
|
+
}
|
|
52
|
+
get parent() {
|
|
53
|
+
return new _Path(dirname(this.#path));
|
|
54
|
+
}
|
|
55
|
+
// Normally I'd stick with `node`'s name, but I think `.dirname` is a
|
|
56
|
+
// particularly poor name. So we support `.dirname` for discovery but mark it
|
|
57
|
+
// as deprecated, even if it will never be removed.
|
|
58
|
+
/** @deprecated Alias for `.parent`. */
|
|
59
|
+
get dirname() {
|
|
60
|
+
return this.parent;
|
|
61
|
+
}
|
|
62
|
+
get basename() {
|
|
63
|
+
return new _Path(basename(this.#path));
|
|
64
|
+
}
|
|
65
|
+
get extension() {
|
|
66
|
+
this.#mustNotHaveTrailingSlash();
|
|
67
|
+
return extname(this.#path);
|
|
68
|
+
}
|
|
69
|
+
// Normally I'd stick with `node`'s name, but I think `.extname` is a
|
|
70
|
+
// particularly poor name. So we support `.extname` for discovery but mark it
|
|
71
|
+
// as deprecated, even if it will never be removed.
|
|
72
|
+
/** @deprecated Alias for `.extension`. */
|
|
73
|
+
get extname() {
|
|
74
|
+
return this.extension;
|
|
75
|
+
}
|
|
76
|
+
#mustNotHaveTrailingSlash() {
|
|
77
|
+
if (this.#path.endsWith("/")) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
"Path ends with a slash, which cannot be treated as a file."
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async exists(constraints) {
|
|
84
|
+
let stats;
|
|
85
|
+
try {
|
|
86
|
+
stats = await stat(this.#path);
|
|
87
|
+
} catch (e) {
|
|
88
|
+
if (e.code === "ENOENT") {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
throw e;
|
|
92
|
+
}
|
|
93
|
+
if (!constraints?.mustBe) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
switch (constraints?.mustBe) {
|
|
97
|
+
case "file": {
|
|
98
|
+
this.#mustNotHaveTrailingSlash();
|
|
99
|
+
if (stats.isFile()) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
throw new Error(`Path exists but is not a file: ${this.#path}`);
|
|
103
|
+
}
|
|
104
|
+
case "directory": {
|
|
105
|
+
if (stats.isDirectory()) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
throw new Error(`Path exists but is not a directory: ${this.#path}`);
|
|
109
|
+
}
|
|
110
|
+
default: {
|
|
111
|
+
throw new Error("Invalid path type constraint");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async existsAsFile() {
|
|
116
|
+
return this.exists({ mustBe: "file" });
|
|
117
|
+
}
|
|
118
|
+
async existsAsDir() {
|
|
119
|
+
return this.exists({ mustBe: "directory" });
|
|
120
|
+
}
|
|
121
|
+
// I don't think `mkdir` is a great name, but it does match the
|
|
122
|
+
// well-established canonical commandline name. So in this case we keep the
|
|
123
|
+
// awkward abbreviation.
|
|
124
|
+
/** Defaults to `recursive: true`. */
|
|
125
|
+
async mkdir(options) {
|
|
126
|
+
const optionsObject = (() => {
|
|
127
|
+
if (typeof options === "string" || typeof options === "number") {
|
|
128
|
+
return { mode: options };
|
|
129
|
+
}
|
|
130
|
+
return options ?? {};
|
|
131
|
+
})();
|
|
132
|
+
await mkdir(this.#path, { recursive: true, ...optionsObject });
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
// TODO: check idempotency semantics when the destination exists and is a folder.
|
|
136
|
+
/** Returns the destination path. */
|
|
137
|
+
async cp(destination, options) {
|
|
138
|
+
await cp(this.#path, new _Path(destination).#path, options);
|
|
139
|
+
return new _Path(destination);
|
|
140
|
+
}
|
|
141
|
+
// TODO: check idempotency semantics when the destination exists and is a folder.
|
|
142
|
+
async rename(destination) {
|
|
143
|
+
await rename(this.#path, new _Path(destination).#path);
|
|
144
|
+
}
|
|
145
|
+
/** Create a temporary dir inside the global temp dir for the current user. */
|
|
146
|
+
static async makeTempDir(prefix) {
|
|
147
|
+
return new _Path(
|
|
148
|
+
await mkdtemp(new _Path(tmpdir()).join(prefix ?? "js-temp-").toString())
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
async trash() {
|
|
152
|
+
await trash(this.#path, { glob: false });
|
|
153
|
+
}
|
|
154
|
+
async fileText() {
|
|
155
|
+
return readFile(this.#path, "utf-8");
|
|
156
|
+
}
|
|
157
|
+
async fileJSON() {
|
|
158
|
+
return JSON.parse(await this.fileText());
|
|
159
|
+
}
|
|
160
|
+
/** Returns the original `Path` (for chaining). */
|
|
161
|
+
async write(data, options) {
|
|
162
|
+
await writeFile(this.#path, data, options);
|
|
163
|
+
return this;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* If only `data` is provided, this is equivalent to:
|
|
167
|
+
*
|
|
168
|
+
* .write(JSON.stringify(data, null, " "));
|
|
169
|
+
*
|
|
170
|
+
* `replacer` and `space` can also be specified, making this equivalent to:
|
|
171
|
+
*
|
|
172
|
+
* .write(JSON.stringify(data, replacer, space));
|
|
173
|
+
*
|
|
174
|
+
* Returns the original `Path` (for chaining).
|
|
175
|
+
*/
|
|
176
|
+
async writeJSON(data, replacer = null, space = " ") {
|
|
177
|
+
await this.write(JSON.stringify(data, replacer, space));
|
|
178
|
+
return this;
|
|
179
|
+
}
|
|
180
|
+
static get homedir() {
|
|
181
|
+
return new _Path(homedir());
|
|
182
|
+
}
|
|
183
|
+
static xdg = {
|
|
184
|
+
cache: new _Path(xdgCache ?? _Path.homedir.join(".cache")),
|
|
185
|
+
config: new _Path(xdgConfig ?? _Path.homedir.join(".config")),
|
|
186
|
+
data: new _Path(xdgData ?? _Path.homedir.join(".local/share")),
|
|
187
|
+
state: new _Path(xdgState ?? _Path.homedir.join(".local/state"))
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
export {
|
|
191
|
+
Path
|
|
192
|
+
};
|
|
193
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n cp,\n mkdir,\n mkdtemp,\n readFile,\n rename,\n stat,\n writeFile,\n} from \"node:fs/promises\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { basename, dirname, extname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { default as trash } from \"trash\";\nimport { xdgCache, xdgConfig, xdgData, xdgState } from \"xdg-basedir\";\n\n// TODO: classes for relative vs. absolute?\n\nexport class Path {\n // @ts-expect-error ts(2564): False positive. https://github.com/microsoft/TypeScript/issues/32194\n #path: string;\n constructor(path: string | URL | Path) {\n if (path instanceof Path) {\n this.#setNormalizedPath(path.#path);\n return;\n }\n if (path instanceof URL) {\n this.#setNormalizedPath(fileURLToPath(path));\n return;\n }\n if (typeof path === \"string\") {\n this.#setNormalizedPath(path);\n return;\n }\n throw new Error(\"Invalid path\");\n }\n\n #setNormalizedPath(path: string): void {\n this.#path = join(path);\n }\n\n toString(): string {\n return this.#path;\n }\n\n /// Constructs a new path by appending the given path segments.\n // TODO: accept `Path` inputs?\n join(...segments: string[]): Path {\n return new Path(join(this.#path, ...segments));\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 this.#mustNotHaveTrailingSlash();\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 #mustNotHaveTrailingSlash(): void {\n if (this.#path.endsWith(\"/\")) {\n throw new Error(\n \"Path ends with a slash, which cannot be treated as a file.\",\n );\n }\n }\n\n async exists(constraints?: {\n mustBe: \"file\" | \"directory\";\n }): Promise<boolean> {\n let stats: Awaited<ReturnType<typeof stat>>;\n try {\n stats = await stat(this.#path);\n // biome-ignore lint/suspicious/noExplicitAny: TypeScript limitation\n } catch (e: any) {\n if (e.code === \"ENOENT\") {\n return false;\n }\n throw e;\n }\n if (!constraints?.mustBe) {\n return true;\n }\n switch (constraints?.mustBe) {\n case \"file\": {\n this.#mustNotHaveTrailingSlash();\n if (stats.isFile()) {\n return true;\n }\n throw new Error(`Path exists but is not a file: ${this.#path}`);\n }\n case \"directory\": {\n if (stats.isDirectory()) {\n return true;\n }\n throw new Error(`Path exists but is not a directory: ${this.#path}`);\n }\n default: {\n throw new Error(\"Invalid path type constraint\");\n }\n }\n }\n\n async existsAsFile(): Promise<boolean> {\n return this.exists({ mustBe: \"file\" });\n }\n\n async existsAsDir(): Promise<boolean> {\n return this.exists({ mustBe: \"directory\" });\n }\n\n // I don't think `mkdir` is a great name, but it does match the\n // well-established canonical commandline name. So in this case we keep the\n // awkward abbreviation.\n /** Defaults to `recursive: true`. */\n async mkdir(options?: Parameters<typeof mkdir>[1]): Promise<Path> {\n const optionsObject = (() => {\n if (typeof options === \"string\" || typeof options === \"number\") {\n return { mode: options };\n }\n return options ?? {};\n })();\n await mkdir(this.#path, { recursive: true, ...optionsObject });\n return this;\n }\n\n // TODO: check idempotency semantics when the destination exists and is a folder.\n /** Returns the destination path. */\n async cp(\n destination: string | URL | Path,\n options?: Parameters<typeof cp>[2],\n ): Promise<Path> {\n await cp(this.#path, new Path(destination).#path, options);\n return new Path(destination);\n }\n\n // TODO: check idempotency semantics when the destination exists and is a folder.\n async rename(destination: string | URL | Path): Promise<void> {\n await rename(this.#path, new Path(destination).#path);\n }\n\n /** Create a temporary dir inside the global temp dir for the current user. */\n static async makeTempDir(prefix?: string): Promise<Path> {\n return new Path(\n await mkdtemp(new Path(tmpdir()).join(prefix ?? \"js-temp-\").toString()),\n );\n }\n\n async trash(): Promise<void> {\n await trash(this.#path, { glob: false });\n }\n\n async fileText(): Promise<string> {\n return readFile(this.#path, \"utf-8\");\n }\n\n async fileJSON<T>(): Promise<T> {\n return JSON.parse(await this.fileText());\n }\n\n /** Returns the original `Path` (for chaining). */\n async write(\n data: Parameters<typeof writeFile>[1],\n options?: Parameters<typeof writeFile>[2],\n ): Promise<Path> {\n await writeFile(this.#path, data, options);\n return this;\n }\n\n /**\n * If only `data` is provided, this is equivalent to:\n *\n * .write(JSON.stringify(data, null, \" \"));\n *\n * `replacer` and `space` can also be specified, making this equivalent to:\n *\n * .write(JSON.stringify(data, replacer, space));\n *\n * Returns the original `Path` (for chaining).\n */\n async writeJSON<T>(\n data: T,\n replacer: Parameters<typeof JSON.stringify>[1] = null,\n space: Parameters<typeof JSON.stringify>[2] = \" \",\n ): Promise<Path> {\n await this.write(JSON.stringify(data, replacer, space));\n return this;\n }\n\n static get homedir(): Path {\n return new Path(homedir());\n }\n\n static xdg = {\n cache: new Path(xdgCache ?? Path.homedir.join(\".cache\")),\n config: new Path(xdgConfig ?? Path.homedir.join(\".config\")),\n data: new Path(xdgData ?? Path.homedir.join(\".local/share\")),\n state: new Path(xdgState ?? Path.homedir.join(\".local/state\")),\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "path-class",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"author": "Lucas Garron <code@garron.net>",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./
|
|
6
|
+
"main": "./dist/lib/path-class/index.js",
|
|
7
|
+
"types": "./dist/lib/path-class/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/lib/path-class/index.d.ts",
|
|
11
|
+
"import": "./dist/lib/path-class/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
7
14
|
"devDependencies": {
|
|
8
15
|
"@biomejs/biome": "^2.2.5",
|
|
9
|
-
"@cubing/dev-config": "^0.3.6"
|
|
16
|
+
"@cubing/dev-config": "^0.3.6",
|
|
17
|
+
"@types/bun": "^1.3.0",
|
|
18
|
+
"esbuild": "^0.25.10"
|
|
10
19
|
},
|
|
11
20
|
"dependencies": {
|
|
12
|
-
"@types/node": "^24.7.
|
|
21
|
+
"@types/node": "^24.7.1",
|
|
13
22
|
"trash": "^10.0.0",
|
|
23
|
+
"typescript": "^5.9.3",
|
|
14
24
|
"xdg-basedir": "^5.1.0"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"./dist/",
|
|
28
|
+
"./src"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"prepublishOnly": "make prepublishOnly"
|
|
15
32
|
}
|
|
16
33
|
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { Path } from ".";
|
|
4
|
+
|
|
5
|
+
test("constructor", async () => {
|
|
6
|
+
expect(new Path("foo").toString()).toEqual("foo");
|
|
7
|
+
expect(new Path("./relative").toString()).toEqual("relative");
|
|
8
|
+
expect(new Path("./relative/nested").toString()).toEqual("relative/nested");
|
|
9
|
+
expect(new Path("/absolute").toString()).toEqual("/absolute");
|
|
10
|
+
expect(new Path("/absolute/nested").toString()).toEqual("/absolute/nested");
|
|
11
|
+
expect(new Path("trailing/slash/").toString()).toEqual("trailing/slash/");
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("normalize", async () => {
|
|
15
|
+
expect(new Path("foo//bar").toString()).toEqual("foo/bar");
|
|
16
|
+
expect(new Path("foo////bar").toString()).toEqual("foo/bar");
|
|
17
|
+
expect(new Path("foo/bar/").toString()).toEqual("foo/bar/");
|
|
18
|
+
expect(new Path("foo/bar//").toString()).toEqual("foo/bar/");
|
|
19
|
+
expect(new Path("//absolute////bar").toString()).toEqual("/absolute/bar");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("join", async () => {
|
|
23
|
+
expect(new Path("foo").join("bar").toString()).toEqual("foo/bar");
|
|
24
|
+
expect(new Path("foo/bar").join("bath", "kitchen/sink").toString()).toEqual(
|
|
25
|
+
"foo/bar/bath/kitchen/sink",
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("traverse", async () => {
|
|
30
|
+
expect(new Path("foo/bar").join("..").toString()).toEqual("foo");
|
|
31
|
+
expect(new Path("foo/bar").join(".").toString()).toEqual("foo/bar");
|
|
32
|
+
expect(new Path("foo/bar").join("../baz").toString()).toEqual("foo/baz");
|
|
33
|
+
expect(new Path("/absolute/path").join("../..").toString()).toEqual("/");
|
|
34
|
+
expect(new Path("/absolute/path").join("../../..").toString()).toEqual("/");
|
|
35
|
+
expect(new Path("/").join("..").toString()).toEqual("/");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test(".extendBasename(…)", async () => {
|
|
39
|
+
expect(
|
|
40
|
+
new Path("file.mp4").extendBasename(".hevc.qv65.mov").toString(),
|
|
41
|
+
).toEqual("file.mp4.hevc.qv65.mov");
|
|
42
|
+
// Trailing dots should not be removed.
|
|
43
|
+
expect(
|
|
44
|
+
new Path("file.mp4.").extendBasename(".hevc.qv65.mov").toString(),
|
|
45
|
+
).toEqual("file.mp4..hevc.qv65.mov");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test(".parent", async () => {
|
|
49
|
+
expect(new Path("/").parent.toString()).toEqual("/");
|
|
50
|
+
expect(new Path("dir").parent.toString()).toEqual(".");
|
|
51
|
+
expect(new Path("dir/").parent.toString()).toEqual(".");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test(".dirname", async () => {
|
|
55
|
+
expect(new Path("/").dirname.toString()).toEqual("/");
|
|
56
|
+
expect(new Path("dir").dirname.toString()).toEqual(".");
|
|
57
|
+
expect(new Path("dir/").dirname.toString()).toEqual(".");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test(".basename", async () => {
|
|
61
|
+
expect(new Path("/").basename.toString()).toEqual("."); // TODO?
|
|
62
|
+
expect(new Path("dir").basename.toString()).toEqual("dir");
|
|
63
|
+
expect(new Path("dir/").basename.toString()).toEqual("dir");
|
|
64
|
+
expect(Path.xdg.config.join("foo/bar.json").basename.toString()).toEqual(
|
|
65
|
+
"bar.json",
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test(".extension", async () => {
|
|
70
|
+
expect(new Path("foo.txt").extension).toEqual(".txt");
|
|
71
|
+
expect(new Path("foo.").extension).toEqual(".");
|
|
72
|
+
expect(new Path("foo").extension).toEqual("");
|
|
73
|
+
expect(() => new Path("dir/").extension).toThrow();
|
|
74
|
+
expect(() => new Path("/").extension).toThrow();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test(".extname", async () => {
|
|
78
|
+
expect(new Path("foo.txt").extname).toEqual(".txt");
|
|
79
|
+
expect(new Path("foo.").extname).toEqual(".");
|
|
80
|
+
expect(new Path("foo").extname).toEqual("");
|
|
81
|
+
expect(() => new Path("dir/").extname).toThrow();
|
|
82
|
+
expect(() => new Path("/").extname).toThrow();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test(".existsAsFile()", async () => {
|
|
86
|
+
const filePath = (await Path.makeTempDir()).join("file.txt");
|
|
87
|
+
expect(await filePath.exists()).toBe(false);
|
|
88
|
+
expect(await filePath.exists({ mustBe: "file" })).toBe(false);
|
|
89
|
+
expect(await filePath.exists({ mustBe: "directory" })).toBe(false);
|
|
90
|
+
expect(await filePath.existsAsFile()).toBe(false);
|
|
91
|
+
await filePath.write("test");
|
|
92
|
+
expect(await filePath.exists()).toBe(true);
|
|
93
|
+
expect(await filePath.exists({ mustBe: "file" })).toBe(true);
|
|
94
|
+
expect(() => filePath.exists({ mustBe: "directory" })).toThrow(
|
|
95
|
+
/Path exists but is not a directory/,
|
|
96
|
+
);
|
|
97
|
+
expect(await filePath.existsAsFile()).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test(".existsAsDir()", async () => {
|
|
101
|
+
const filePath = await Path.makeTempDir();
|
|
102
|
+
expect(await filePath.exists()).toBe(true);
|
|
103
|
+
expect(() => filePath.exists({ mustBe: "file" })).toThrow(
|
|
104
|
+
/Path exists but is not a file/,
|
|
105
|
+
);
|
|
106
|
+
expect(await filePath.exists({ mustBe: "directory" })).toBe(true);
|
|
107
|
+
expect(await filePath.existsAsDir()).toBe(true);
|
|
108
|
+
await filePath.trash();
|
|
109
|
+
expect(await filePath.exists()).toBe(false);
|
|
110
|
+
expect(await filePath.exists({ mustBe: "file" })).toBe(false);
|
|
111
|
+
expect(await filePath.exists({ mustBe: "directory" })).toBe(false);
|
|
112
|
+
expect(await filePath.existsAsDir()).toBe(false);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("mkdir (un-nested)", async () => {
|
|
116
|
+
const dir = (await Path.makeTempDir()).join("mkdir-test");
|
|
117
|
+
expect(await dir.exists()).toBe(false);
|
|
118
|
+
await dir.mkdir();
|
|
119
|
+
expect(await dir.exists()).toBe(true);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("mkdir (nested)", async () => {
|
|
123
|
+
const dir = (await Path.makeTempDir()).join("mkdir-test/nested");
|
|
124
|
+
expect(await dir.exists()).toBe(false);
|
|
125
|
+
expect(() => dir.mkdir({ recursive: false })).toThrow("no such file");
|
|
126
|
+
await dir.mkdir();
|
|
127
|
+
expect(await dir.exists()).toBe(true);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test(".rename()", async () => {
|
|
131
|
+
const parentDir = await Path.makeTempDir();
|
|
132
|
+
const file1 = parentDir.join("file1.txt");
|
|
133
|
+
const file2 = parentDir.join("file2.txt");
|
|
134
|
+
|
|
135
|
+
await file1.write("hello world");
|
|
136
|
+
expect(await file1.exists()).toBe(true);
|
|
137
|
+
expect(await file2.exists()).toBe(false);
|
|
138
|
+
|
|
139
|
+
await file1.rename(file2);
|
|
140
|
+
expect(await file1.exists()).toBe(false);
|
|
141
|
+
expect(await file2.exists()).toBe(true);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("trash", async () => {
|
|
145
|
+
const tempDir = await Path.makeTempDir();
|
|
146
|
+
expect(tempDir.toString()).toContain("/js-temp-");
|
|
147
|
+
expect(await tempDir.exists()).toBe(true);
|
|
148
|
+
await tempDir.trash();
|
|
149
|
+
expect(await tempDir.exists()).toBe(false);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test(".fileText()", async () => {
|
|
153
|
+
const file = (await Path.makeTempDir()).join("file.txt");
|
|
154
|
+
await file.write("hi");
|
|
155
|
+
await file.write("bye");
|
|
156
|
+
|
|
157
|
+
expect(await file.fileText()).toBe("bye");
|
|
158
|
+
expect(await readFile(file.toString(), "utf-8")).toBe("bye");
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test(".fileJSON()", async () => {
|
|
162
|
+
const file = (await Path.makeTempDir()).join("file.json");
|
|
163
|
+
await file.write(JSON.stringify({ foo: "bar" }));
|
|
164
|
+
|
|
165
|
+
expect(await file.fileJSON()).toEqual<Record<string, string>>({ foo: "bar" });
|
|
166
|
+
expect(await file.fileJSON<Record<string, string>>()).toEqual({ foo: "bar" });
|
|
167
|
+
expect(await JSON.parse(await readFile(file.toString(), "utf-8"))).toEqual<
|
|
168
|
+
Record<string, string>
|
|
169
|
+
>({ foo: "bar" });
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test(".write(…)", async () => {
|
|
173
|
+
const file = (await Path.makeTempDir()).join("file.json");
|
|
174
|
+
await file.write("foo");
|
|
175
|
+
|
|
176
|
+
expect(await file.fileText()).toEqual("foo");
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test(".writeJSON(…)", async () => {
|
|
180
|
+
const file = (await Path.makeTempDir()).join("file.json");
|
|
181
|
+
await file.writeJSON({ foo: "bar" });
|
|
182
|
+
|
|
183
|
+
expect(await file.fileJSON()).toEqual<Record<string, string>>({ foo: "bar" });
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test("homedir", async () => {
|
|
187
|
+
expect(Path.homedir.toString()).toEqual("/mock/home/dir");
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test("XDG", async () => {
|
|
191
|
+
expect(Path.xdg.cache.toString()).toEqual("/mock/home/dir/.cache");
|
|
192
|
+
expect(Path.xdg.config.toString()).toEqual("/xdg/config");
|
|
193
|
+
expect(Path.xdg.data.toString()).toEqual("/mock/home/dir/.local/share");
|
|
194
|
+
expect(Path.xdg.state.toString()).toEqual("/mock/home/dir/.local/state");
|
|
195
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
cp,
|
|
3
|
+
mkdir,
|
|
4
|
+
mkdtemp,
|
|
5
|
+
readFile,
|
|
6
|
+
rename,
|
|
7
|
+
stat,
|
|
8
|
+
writeFile,
|
|
9
|
+
} from "node:fs/promises";
|
|
10
|
+
import { homedir, tmpdir } from "node:os";
|
|
11
|
+
import { basename, dirname, extname, join } from "node:path";
|
|
4
12
|
import { fileURLToPath } from "node:url";
|
|
5
13
|
import { default as trash } from "trash";
|
|
6
14
|
import { xdgCache, xdgConfig, xdgData, xdgState } from "xdg-basedir";
|
|
@@ -26,7 +34,7 @@ export class Path {
|
|
|
26
34
|
throw new Error("Invalid path");
|
|
27
35
|
}
|
|
28
36
|
|
|
29
|
-
#setNormalizedPath(path: string) {
|
|
37
|
+
#setNormalizedPath(path: string): void {
|
|
30
38
|
this.#path = join(path);
|
|
31
39
|
}
|
|
32
40
|
|
|
@@ -53,8 +61,37 @@ export class Path {
|
|
|
53
61
|
return new Path(dirname(this.#path));
|
|
54
62
|
}
|
|
55
63
|
|
|
56
|
-
|
|
57
|
-
|
|
64
|
+
// Normally I'd stick with `node`'s name, but I think `.dirname` is a
|
|
65
|
+
// particularly poor name. So we support `.dirname` for discovery but mark it
|
|
66
|
+
// as deprecated, even if it will never be removed.
|
|
67
|
+
/** @deprecated Alias for `.parent`. */
|
|
68
|
+
get dirname(): Path {
|
|
69
|
+
return this.parent;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get basename(): Path {
|
|
73
|
+
return new Path(basename(this.#path));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
get extension(): string {
|
|
77
|
+
this.#mustNotHaveTrailingSlash();
|
|
78
|
+
return extname(this.#path);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Normally I'd stick with `node`'s name, but I think `.extname` is a
|
|
82
|
+
// particularly poor name. So we support `.extname` for discovery but mark it
|
|
83
|
+
// as deprecated, even if it will never be removed.
|
|
84
|
+
/** @deprecated Alias for `.extension`. */
|
|
85
|
+
get extname(): string {
|
|
86
|
+
return this.extension;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
#mustNotHaveTrailingSlash(): void {
|
|
90
|
+
if (this.#path.endsWith("/")) {
|
|
91
|
+
throw new Error(
|
|
92
|
+
"Path ends with a slash, which cannot be treated as a file.",
|
|
93
|
+
);
|
|
94
|
+
}
|
|
58
95
|
}
|
|
59
96
|
|
|
60
97
|
async exists(constraints?: {
|
|
@@ -75,6 +112,7 @@ export class Path {
|
|
|
75
112
|
}
|
|
76
113
|
switch (constraints?.mustBe) {
|
|
77
114
|
case "file": {
|
|
115
|
+
this.#mustNotHaveTrailingSlash();
|
|
78
116
|
if (stats.isFile()) {
|
|
79
117
|
return true;
|
|
80
118
|
}
|
|
@@ -100,18 +138,45 @@ export class Path {
|
|
|
100
138
|
return this.exists({ mustBe: "directory" });
|
|
101
139
|
}
|
|
102
140
|
|
|
103
|
-
|
|
104
|
-
|
|
141
|
+
// I don't think `mkdir` is a great name, but it does match the
|
|
142
|
+
// well-established canonical commandline name. So in this case we keep the
|
|
143
|
+
// awkward abbreviation.
|
|
144
|
+
/** Defaults to `recursive: true`. */
|
|
145
|
+
async mkdir(options?: Parameters<typeof mkdir>[1]): Promise<Path> {
|
|
146
|
+
const optionsObject = (() => {
|
|
147
|
+
if (typeof options === "string" || typeof options === "number") {
|
|
148
|
+
return { mode: options };
|
|
149
|
+
}
|
|
150
|
+
return options ?? {};
|
|
151
|
+
})();
|
|
152
|
+
await mkdir(this.#path, { recursive: true, ...optionsObject });
|
|
153
|
+
return this;
|
|
105
154
|
}
|
|
106
155
|
|
|
107
156
|
// TODO: check idempotency semantics when the destination exists and is a folder.
|
|
108
|
-
|
|
109
|
-
|
|
157
|
+
/** Returns the destination path. */
|
|
158
|
+
async cp(
|
|
159
|
+
destination: string | URL | Path,
|
|
160
|
+
options?: Parameters<typeof cp>[2],
|
|
161
|
+
): Promise<Path> {
|
|
162
|
+
await cp(this.#path, new Path(destination).#path, options);
|
|
163
|
+
return new Path(destination);
|
|
110
164
|
}
|
|
111
165
|
|
|
112
166
|
// TODO: check idempotency semantics when the destination exists and is a folder.
|
|
167
|
+
async rename(destination: string | URL | Path): Promise<void> {
|
|
168
|
+
await rename(this.#path, new Path(destination).#path);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Create a temporary dir inside the global temp dir for the current user. */
|
|
172
|
+
static async makeTempDir(prefix?: string): Promise<Path> {
|
|
173
|
+
return new Path(
|
|
174
|
+
await mkdtemp(new Path(tmpdir()).join(prefix ?? "js-temp-").toString()),
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
113
178
|
async trash(): Promise<void> {
|
|
114
|
-
await trash(this.#path);
|
|
179
|
+
await trash(this.#path, { glob: false });
|
|
115
180
|
}
|
|
116
181
|
|
|
117
182
|
async fileText(): Promise<string> {
|
|
@@ -122,8 +187,33 @@ export class Path {
|
|
|
122
187
|
return JSON.parse(await this.fileText());
|
|
123
188
|
}
|
|
124
189
|
|
|
125
|
-
|
|
126
|
-
|
|
190
|
+
/** Returns the original `Path` (for chaining). */
|
|
191
|
+
async write(
|
|
192
|
+
data: Parameters<typeof writeFile>[1],
|
|
193
|
+
options?: Parameters<typeof writeFile>[2],
|
|
194
|
+
): Promise<Path> {
|
|
195
|
+
await writeFile(this.#path, data, options);
|
|
196
|
+
return this;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* If only `data` is provided, this is equivalent to:
|
|
201
|
+
*
|
|
202
|
+
* .write(JSON.stringify(data, null, " "));
|
|
203
|
+
*
|
|
204
|
+
* `replacer` and `space` can also be specified, making this equivalent to:
|
|
205
|
+
*
|
|
206
|
+
* .write(JSON.stringify(data, replacer, space));
|
|
207
|
+
*
|
|
208
|
+
* Returns the original `Path` (for chaining).
|
|
209
|
+
*/
|
|
210
|
+
async writeJSON<T>(
|
|
211
|
+
data: T,
|
|
212
|
+
replacer: Parameters<typeof JSON.stringify>[1] = null,
|
|
213
|
+
space: Parameters<typeof JSON.stringify>[2] = " ",
|
|
214
|
+
): Promise<Path> {
|
|
215
|
+
await this.write(JSON.stringify(data, replacer, space));
|
|
216
|
+
return this;
|
|
127
217
|
}
|
|
128
218
|
|
|
129
219
|
static get homedir(): Path {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { mock } from "bun:test";
|
|
2
|
+
import nodeOS from "node:os";
|
|
3
|
+
|
|
4
|
+
const nodeOSMocked = {
|
|
5
|
+
...nodeOS,
|
|
6
|
+
homedir: () => "/mock/home/dir",
|
|
7
|
+
};
|
|
8
|
+
// biome-ignore lint/suspicious/noExplicitAny: This isn't worth wrangling types for.
|
|
9
|
+
(nodeOSMocked as any).default = nodeOSMocked; // Needed because `xdg-basedir` imports the default.
|
|
10
|
+
|
|
11
|
+
mock.module("node:os", () => {
|
|
12
|
+
return nodeOSMocked;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
mock.module("os", () => {
|
|
16
|
+
return nodeOSMocked;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
process.env = { XDG_CONFIG_HOME: "/xdg/config" };
|
package/Makefile
DELETED
package/biome.json
DELETED
package/bun.lock
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"lockfileVersion": 1,
|
|
3
|
-
"workspaces": {
|
|
4
|
-
"": {
|
|
5
|
-
"dependencies": {
|
|
6
|
-
"@types/node": "^24.7.0",
|
|
7
|
-
"trash": "^10.0.0",
|
|
8
|
-
"xdg-basedir": "^5.1.0",
|
|
9
|
-
},
|
|
10
|
-
"devDependencies": {
|
|
11
|
-
"@biomejs/biome": "^2.2.5",
|
|
12
|
-
"@cubing/dev-config": "^0.3.6",
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
"packages": {
|
|
17
|
-
"@biomejs/biome": ["@biomejs/biome@2.2.5", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.2.5", "@biomejs/cli-darwin-x64": "2.2.5", "@biomejs/cli-linux-arm64": "2.2.5", "@biomejs/cli-linux-arm64-musl": "2.2.5", "@biomejs/cli-linux-x64": "2.2.5", "@biomejs/cli-linux-x64-musl": "2.2.5", "@biomejs/cli-win32-arm64": "2.2.5", "@biomejs/cli-win32-x64": "2.2.5" }, "bin": { "biome": "bin/biome" } }, "sha512-zcIi+163Rc3HtyHbEO7CjeHq8DjQRs40HsGbW6vx2WI0tg8mYQOPouhvHSyEnCBAorfYNnKdR64/IxO7xQ5faw=="],
|
|
18
|
-
|
|
19
|
-
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.2.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MYT+nZ38wEIWVcL5xLyOhYQQ7nlWD0b/4mgATW2c8dvq7R4OQjt/XGXFkXrmtWmQofaIM14L7V8qIz/M+bx5QQ=="],
|
|
20
|
-
|
|
21
|
-
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.2.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-FLIEl73fv0R7dI10EnEiZLw+IMz3mWLnF95ASDI0kbx6DDLJjWxE5JxxBfmG+udz1hIDd3fr5wsuP7nwuTRdAg=="],
|
|
22
|
-
|
|
23
|
-
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.2.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-5DjiiDfHqGgR2MS9D+AZ8kOfrzTGqLKywn8hoXpXXlJXIECGQ32t+gt/uiS2XyGBM2XQhR6ztUvbjZWeccFMoQ=="],
|
|
24
|
-
|
|
25
|
-
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.2.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Ov2wgAFwqDvQiESnu7b9ufD1faRa+40uwrohgBopeY84El2TnBDoMNXx6iuQdreoFGjwW8vH6k68G21EpNERw=="],
|
|
26
|
-
|
|
27
|
-
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.2.5", "", { "os": "linux", "cpu": "x64" }, "sha512-fq9meKm1AEXeAWan3uCg6XSP5ObA6F/Ovm89TwaMiy1DNIwdgxPkNwxlXJX8iM6oRbFysYeGnT0OG8diCWb9ew=="],
|
|
28
|
-
|
|
29
|
-
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.2.5", "", { "os": "linux", "cpu": "x64" }, "sha512-AVqLCDb/6K7aPNIcxHaTQj01sl1m989CJIQFQEaiQkGr2EQwyOpaATJ473h+nXDUuAcREhccfRpe/tu+0wu0eQ=="],
|
|
30
|
-
|
|
31
|
-
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.2.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-xaOIad4wBambwJa6mdp1FigYSIF9i7PCqRbvBqtIi9y29QtPVQ13sDGtUnsRoe6SjL10auMzQ6YAe+B3RpZXVg=="],
|
|
32
|
-
|
|
33
|
-
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.2.5", "", { "os": "win32", "cpu": "x64" }, "sha512-F/jhuXCssPFAuciMhHKk00xnCAxJRS/pUzVfXYmOMUp//XW7mO6QeCjsjvnm8L4AO/dG2VOB0O+fJPiJ2uXtIw=="],
|
|
34
|
-
|
|
35
|
-
"@cubing/dev-config": ["@cubing/dev-config@0.3.6", "", { "dependencies": { "esbuild": "^0.25.3" } }, "sha512-ia3X3wXxsMF2fiE1ANWPsPL6Jbyy+BPwl50Pe5hp4Kzvghf1A2U+6Ss2N/i+uZMvdBoLHVW0Sg3wOK+gTpEbHg=="],
|
|
36
|
-
|
|
37
|
-
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.10", "", { "os": "aix", "cpu": "ppc64" }, "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw=="],
|
|
38
|
-
|
|
39
|
-
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.10", "", { "os": "android", "cpu": "arm" }, "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w=="],
|
|
40
|
-
|
|
41
|
-
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.10", "", { "os": "android", "cpu": "arm64" }, "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg=="],
|
|
42
|
-
|
|
43
|
-
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.10", "", { "os": "android", "cpu": "x64" }, "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg=="],
|
|
44
|
-
|
|
45
|
-
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA=="],
|
|
46
|
-
|
|
47
|
-
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg=="],
|
|
48
|
-
|
|
49
|
-
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.10", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg=="],
|
|
50
|
-
|
|
51
|
-
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.10", "", { "os": "freebsd", "cpu": "x64" }, "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA=="],
|
|
52
|
-
|
|
53
|
-
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.10", "", { "os": "linux", "cpu": "arm" }, "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg=="],
|
|
54
|
-
|
|
55
|
-
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ=="],
|
|
56
|
-
|
|
57
|
-
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.10", "", { "os": "linux", "cpu": "ia32" }, "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ=="],
|
|
58
|
-
|
|
59
|
-
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg=="],
|
|
60
|
-
|
|
61
|
-
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA=="],
|
|
62
|
-
|
|
63
|
-
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.10", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA=="],
|
|
64
|
-
|
|
65
|
-
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA=="],
|
|
66
|
-
|
|
67
|
-
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.10", "", { "os": "linux", "cpu": "s390x" }, "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew=="],
|
|
68
|
-
|
|
69
|
-
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.10", "", { "os": "linux", "cpu": "x64" }, "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA=="],
|
|
70
|
-
|
|
71
|
-
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A=="],
|
|
72
|
-
|
|
73
|
-
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.10", "", { "os": "none", "cpu": "x64" }, "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig=="],
|
|
74
|
-
|
|
75
|
-
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.10", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw=="],
|
|
76
|
-
|
|
77
|
-
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.10", "", { "os": "openbsd", "cpu": "x64" }, "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw=="],
|
|
78
|
-
|
|
79
|
-
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag=="],
|
|
80
|
-
|
|
81
|
-
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.10", "", { "os": "sunos", "cpu": "x64" }, "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ=="],
|
|
82
|
-
|
|
83
|
-
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw=="],
|
|
84
|
-
|
|
85
|
-
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.10", "", { "os": "win32", "cpu": "ia32" }, "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw=="],
|
|
86
|
-
|
|
87
|
-
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.10", "", { "os": "win32", "cpu": "x64" }, "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw=="],
|
|
88
|
-
|
|
89
|
-
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
|
90
|
-
|
|
91
|
-
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
|
|
92
|
-
|
|
93
|
-
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
|
94
|
-
|
|
95
|
-
"@sindresorhus/chunkify": ["@sindresorhus/chunkify@2.0.0", "", {}, "sha512-srajPSoMTC98FETCJIeXJhJqB77IRPJSu8g907jLuuioLORHZJ3YAOY2DsP5ebrZrjOrAwjqf+Cgkg/I8TGPpw=="],
|
|
96
|
-
|
|
97
|
-
"@sindresorhus/df": ["@sindresorhus/df@3.1.1", "", { "dependencies": { "execa": "^2.0.1" } }, "sha512-SME/vtXaJcnQ/HpeV6P82Egy+jThn11IKfwW8+/XVoRD0rmPHVTeKMtww1oWdVnMykzVPjmrDN9S8NBndPEHCQ=="],
|
|
98
|
-
|
|
99
|
-
"@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@2.3.0", "", {}, "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg=="],
|
|
100
|
-
|
|
101
|
-
"@stroncium/procfs": ["@stroncium/procfs@1.2.1", "", {}, "sha512-X1Iui3FUNZP18EUvysTHxt+Avu2nlVzyf90YM8OYgP6SGzTzzX/0JgObfO1AQQDzuZtNNz29bVh8h5R97JrjxA=="],
|
|
102
|
-
|
|
103
|
-
"@types/node": ["@types/node@24.7.0", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-IbKooQVqUBrlzWTi79E8Fw78l8k1RNtlDDNWsFZs7XonuQSJ8oNYfEeclhprUldXISRMLzBpILuKgPlIxm+/Yw=="],
|
|
104
|
-
|
|
105
|
-
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
|
106
|
-
|
|
107
|
-
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
|
108
|
-
|
|
109
|
-
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
|
|
110
|
-
|
|
111
|
-
"esbuild": ["esbuild@0.25.10", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.10", "@esbuild/android-arm": "0.25.10", "@esbuild/android-arm64": "0.25.10", "@esbuild/android-x64": "0.25.10", "@esbuild/darwin-arm64": "0.25.10", "@esbuild/darwin-x64": "0.25.10", "@esbuild/freebsd-arm64": "0.25.10", "@esbuild/freebsd-x64": "0.25.10", "@esbuild/linux-arm": "0.25.10", "@esbuild/linux-arm64": "0.25.10", "@esbuild/linux-ia32": "0.25.10", "@esbuild/linux-loong64": "0.25.10", "@esbuild/linux-mips64el": "0.25.10", "@esbuild/linux-ppc64": "0.25.10", "@esbuild/linux-riscv64": "0.25.10", "@esbuild/linux-s390x": "0.25.10", "@esbuild/linux-x64": "0.25.10", "@esbuild/netbsd-arm64": "0.25.10", "@esbuild/netbsd-x64": "0.25.10", "@esbuild/openbsd-arm64": "0.25.10", "@esbuild/openbsd-x64": "0.25.10", "@esbuild/openharmony-arm64": "0.25.10", "@esbuild/sunos-x64": "0.25.10", "@esbuild/win32-arm64": "0.25.10", "@esbuild/win32-ia32": "0.25.10", "@esbuild/win32-x64": "0.25.10" }, "bin": "bin/esbuild" }, "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ=="],
|
|
112
|
-
|
|
113
|
-
"execa": ["execa@2.1.0", "", { "dependencies": { "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^3.0.0", "onetime": "^5.1.0", "p-finally": "^2.0.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" } }, "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw=="],
|
|
114
|
-
|
|
115
|
-
"fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
|
|
116
|
-
|
|
117
|
-
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
|
|
118
|
-
|
|
119
|
-
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
|
|
120
|
-
|
|
121
|
-
"get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
|
|
122
|
-
|
|
123
|
-
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
|
124
|
-
|
|
125
|
-
"globby": ["globby@14.1.0", "", { "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", "fast-glob": "^3.3.3", "ignore": "^7.0.3", "path-type": "^6.0.0", "slash": "^5.1.0", "unicorn-magic": "^0.3.0" } }, "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA=="],
|
|
126
|
-
|
|
127
|
-
"ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
|
128
|
-
|
|
129
|
-
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
|
130
|
-
|
|
131
|
-
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
|
132
|
-
|
|
133
|
-
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
|
134
|
-
|
|
135
|
-
"is-path-inside": ["is-path-inside@4.0.0", "", {}, "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA=="],
|
|
136
|
-
|
|
137
|
-
"is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
|
|
138
|
-
|
|
139
|
-
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
|
140
|
-
|
|
141
|
-
"merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
|
|
142
|
-
|
|
143
|
-
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
|
144
|
-
|
|
145
|
-
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
|
146
|
-
|
|
147
|
-
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
|
148
|
-
|
|
149
|
-
"mount-point": ["mount-point@3.0.0", "", { "dependencies": { "@sindresorhus/df": "^1.0.1", "pify": "^2.3.0", "pinkie-promise": "^2.0.1" } }, "sha512-jAhfD7ZCG+dbESZjcY1SdFVFqSJkh/yGbdsifHcPkvuLRO5ugK0Ssmd9jdATu29BTd4JiN+vkpMzVvsUgP3SZA=="],
|
|
150
|
-
|
|
151
|
-
"move-file": ["move-file@3.1.0", "", { "dependencies": { "path-exists": "^5.0.0" } }, "sha512-4aE3U7CCBWgrQlQDMq8da4woBWDGHioJFiOZ8Ie6Yq2uwYQ9V2kGhTz4x3u6Wc+OU17nw0yc3rJ/lQ4jIiPe3A=="],
|
|
152
|
-
|
|
153
|
-
"npm-run-path": ["npm-run-path@3.1.0", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg=="],
|
|
154
|
-
|
|
155
|
-
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
|
156
|
-
|
|
157
|
-
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
|
|
158
|
-
|
|
159
|
-
"os-homedir": ["os-homedir@1.0.2", "", {}, "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ=="],
|
|
160
|
-
|
|
161
|
-
"p-finally": ["p-finally@2.0.1", "", {}, "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw=="],
|
|
162
|
-
|
|
163
|
-
"p-map": ["p-map@7.0.3", "", {}, "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA=="],
|
|
164
|
-
|
|
165
|
-
"path-exists": ["path-exists@5.0.0", "", {}, "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ=="],
|
|
166
|
-
|
|
167
|
-
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
|
168
|
-
|
|
169
|
-
"path-type": ["path-type@6.0.0", "", {}, "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ=="],
|
|
170
|
-
|
|
171
|
-
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
|
172
|
-
|
|
173
|
-
"pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="],
|
|
174
|
-
|
|
175
|
-
"pinkie": ["pinkie@2.0.4", "", {}, "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg=="],
|
|
176
|
-
|
|
177
|
-
"pinkie-promise": ["pinkie-promise@2.0.1", "", { "dependencies": { "pinkie": "^2.0.0" } }, "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw=="],
|
|
178
|
-
|
|
179
|
-
"pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
|
|
180
|
-
|
|
181
|
-
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
|
182
|
-
|
|
183
|
-
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
|
|
184
|
-
|
|
185
|
-
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
|
186
|
-
|
|
187
|
-
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
|
188
|
-
|
|
189
|
-
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
|
190
|
-
|
|
191
|
-
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
|
192
|
-
|
|
193
|
-
"slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="],
|
|
194
|
-
|
|
195
|
-
"strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
|
|
196
|
-
|
|
197
|
-
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
|
198
|
-
|
|
199
|
-
"trash": ["trash@10.0.0", "", { "dependencies": { "@sindresorhus/chunkify": "^2.0.0", "@stroncium/procfs": "^1.2.1", "globby": "^14.1.0", "is-path-inside": "^4.0.0", "move-file": "^3.1.0", "p-map": "^7.0.3", "xdg-trashdir": "^3.1.0" } }, "sha512-nyHQPJ7F4dYCfj1xN95DAkLkf9qlyRLDpT9yYwcR5SH16q+f7VA1L5VwsdEqWFUuGNpKwgLnbOS1QBvXMYnLfA=="],
|
|
200
|
-
|
|
201
|
-
"undici-types": ["undici-types@7.14.0", "", {}, "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA=="],
|
|
202
|
-
|
|
203
|
-
"unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="],
|
|
204
|
-
|
|
205
|
-
"user-home": ["user-home@2.0.0", "", { "dependencies": { "os-homedir": "^1.0.0" } }, "sha512-KMWqdlOcjCYdtIJpicDSFBQ8nFwS2i9sslAd6f4+CBGcU4gist2REnr2fxj2YocvJFxSF3ZOHLYLVZnUxv4BZQ=="],
|
|
206
|
-
|
|
207
|
-
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
|
208
|
-
|
|
209
|
-
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
|
210
|
-
|
|
211
|
-
"xdg-basedir": ["xdg-basedir@5.1.0", "", {}, "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ=="],
|
|
212
|
-
|
|
213
|
-
"xdg-trashdir": ["xdg-trashdir@3.1.0", "", { "dependencies": { "@sindresorhus/df": "^3.1.1", "mount-point": "^3.0.0", "user-home": "^2.0.0", "xdg-basedir": "^4.0.0" } }, "sha512-N1XQngeqMBoj9wM4ZFadVV2MymImeiFfYD+fJrNlcVcOHsJFFQe7n3b+aBoTPwARuq2HQxukfzVpQmAk1gN4sQ=="],
|
|
214
|
-
|
|
215
|
-
"mount-point/@sindresorhus/df": ["@sindresorhus/df@1.0.1", "", {}, "sha512-1Hyp7NQnD/u4DSxR2DGW78TF9k7R0wZ8ev0BpMAIzA6yTQSHqNb5wTuvtcPYf4FWbVse2rW7RgDsyL8ua2vXHw=="],
|
|
216
|
-
|
|
217
|
-
"xdg-trashdir/xdg-basedir": ["xdg-basedir@4.0.0", "", {}, "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q=="],
|
|
218
|
-
}
|
|
219
|
-
}
|
package/tsconfig.json
DELETED