@sorrell/utilities 1.2.8 → 1.2.11
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/Distribution/PackageExports.Generated.json +30 -0
- package/Distribution/Types/FileSystem/FileSystem.d.cts +16 -0
- package/Distribution/Types/FileSystem/FileSystem.d.cts.map +1 -1
- package/Distribution/Types/FileSystem/FileSystem.d.mts +16 -0
- package/Distribution/Types/FileSystem/FileSystem.d.mts.map +1 -1
- package/Distribution/Types/FileSystem/FileSystem.d.ts +16 -0
- package/Distribution/Types/FileSystem/FileSystem.d.ts.map +1 -1
- package/Distribution/Types/Functional/Functional.d.cts +7 -1
- package/Distribution/Types/Functional/Functional.d.cts.map +1 -1
- package/Distribution/Types/Functional/Functional.d.mts +7 -1
- package/Distribution/Types/Functional/Functional.d.mts.map +1 -1
- package/Distribution/Types/Functional/Functional.d.ts +7 -1
- package/Distribution/Types/Functional/Functional.d.ts.map +1 -1
- package/Distribution/Types/HigherKind/HigherKind.Internal.Types.d.cts +30 -0
- package/Distribution/Types/HigherKind/HigherKind.Internal.Types.d.cts.map +10 -0
- package/Distribution/Types/HigherKind/HigherKind.Internal.Types.d.mts +30 -0
- package/Distribution/Types/HigherKind/HigherKind.Internal.Types.d.mts.map +10 -0
- package/Distribution/Types/HigherKind/HigherKind.Internal.Types.d.ts +30 -0
- package/Distribution/Types/HigherKind/HigherKind.Internal.Types.d.ts.map +1 -0
- package/Distribution/Types/HigherKind/HigherKind.Registrar.Types.d.cts +31 -0
- package/Distribution/Types/HigherKind/HigherKind.Registrar.Types.d.cts.map +10 -0
- package/Distribution/Types/HigherKind/HigherKind.Registrar.Types.d.mts +31 -0
- package/Distribution/Types/HigherKind/HigherKind.Registrar.Types.d.mts.map +10 -0
- package/Distribution/Types/HigherKind/HigherKind.Registrar.Types.d.ts +31 -0
- package/Distribution/Types/HigherKind/HigherKind.Registrar.Types.d.ts.map +1 -0
- package/Distribution/Types/HigherKind/HigherKind.Types.d.cts +85 -0
- package/Distribution/Types/HigherKind/HigherKind.Types.d.cts.map +10 -0
- package/Distribution/Types/HigherKind/HigherKind.Types.d.mts +85 -0
- package/Distribution/Types/HigherKind/HigherKind.Types.d.mts.map +10 -0
- package/Distribution/Types/HigherKind/HigherKind.Types.d.ts +85 -0
- package/Distribution/Types/HigherKind/HigherKind.Types.d.ts.map +1 -0
- package/Distribution/Types/HigherKind/index.d.cts +8 -0
- package/Distribution/Types/HigherKind/index.d.cts.map +10 -0
- package/Distribution/Types/HigherKind/index.d.mts +8 -0
- package/Distribution/Types/HigherKind/index.d.mts.map +10 -0
- package/Distribution/Types/HigherKind/index.d.ts +8 -0
- package/Distribution/Types/HigherKind/index.d.ts.map +1 -0
- package/Distribution/Types/Miscellaneous/Utility.Types.d.cts +12 -26
- package/Distribution/Types/Miscellaneous/Utility.Types.d.cts.map +1 -1
- package/Distribution/Types/Miscellaneous/Utility.Types.d.mts +12 -26
- package/Distribution/Types/Miscellaneous/Utility.Types.d.mts.map +1 -1
- package/Distribution/Types/Miscellaneous/Utility.Types.d.ts +12 -26
- package/Distribution/Types/Miscellaneous/Utility.Types.d.ts.map +1 -1
- package/Distribution/Types/String/String.d.cts +55 -10
- package/Distribution/Types/String/String.d.cts.map +1 -1
- package/Distribution/Types/String/String.d.mts +55 -10
- package/Distribution/Types/String/String.d.mts.map +1 -1
- package/Distribution/Types/String/String.d.ts +55 -10
- package/Distribution/Types/String/String.d.ts.map +1 -1
- package/Distribution/Types/TsConfig/TsConfig.Types.d.cts +32 -0
- package/Distribution/Types/TsConfig/TsConfig.Types.d.cts.map +10 -0
- package/Distribution/Types/TsConfig/TsConfig.Types.d.mts +32 -0
- package/Distribution/Types/TsConfig/TsConfig.Types.d.mts.map +10 -0
- package/Distribution/Types/TsConfig/TsConfig.Types.d.ts +32 -0
- package/Distribution/Types/TsConfig/TsConfig.Types.d.ts.map +1 -0
- package/Distribution/Types/TsConfig/index.d.cts +8 -0
- package/Distribution/Types/TsConfig/index.d.cts.map +10 -0
- package/Distribution/Types/TsConfig/index.d.mts +8 -0
- package/Distribution/Types/TsConfig/index.d.mts.map +10 -0
- package/Distribution/Types/TsConfig/index.d.ts +8 -0
- package/Distribution/Types/TsConfig/index.d.ts.map +1 -0
- package/Distribution/Types/index.d.cts +1 -0
- package/Distribution/Types/index.d.cts.map +1 -1
- package/Distribution/Types/index.d.mts +1 -0
- package/Distribution/Types/index.d.mts.map +1 -1
- package/Distribution/Types/index.d.ts +1 -0
- package/Distribution/Types/index.d.ts.map +1 -1
- package/Distribution/async.cjs.map +2 -2
- package/Distribution/async.js.map +2 -2
- package/Distribution/fs.cjs +94 -4
- package/Distribution/fs.cjs.map +3 -3
- package/Distribution/fs.js +94 -4
- package/Distribution/fs.js.map +3 -3
- package/Distribution/functional.cjs +2 -2
- package/Distribution/functional.cjs.map +2 -2
- package/Distribution/functional.js +2 -2
- package/Distribution/functional.js.map +2 -2
- package/Distribution/higher-kind.cjs +31 -0
- package/Distribution/higher-kind.cjs.map +7 -0
- package/Distribution/higher-kind.js +13 -0
- package/Distribution/higher-kind.js.map +7 -0
- package/Distribution/index.cjs +137 -18
- package/Distribution/index.cjs.map +4 -4
- package/Distribution/index.js +144 -25
- package/Distribution/index.js.map +4 -4
- package/Distribution/misc.cjs.map +2 -2
- package/Distribution/misc.js.map +2 -2
- package/Distribution/string.cjs +70 -0
- package/Distribution/string.cjs.map +7 -0
- package/Distribution/string.js +47 -0
- package/Distribution/string.js.map +7 -0
- package/Distribution/tsconfig.cjs +31 -0
- package/Distribution/tsconfig.cjs.map +7 -0
- package/Distribution/tsconfig.js +13 -0
- package/Distribution/tsconfig.js.map +7 -0
- package/package.json +45 -7
package/Distribution/fs.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../Source/FileSystem/index.ts", "../Source/FileSystem/FileSystem.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @file index.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nexport * from \"./FileSystem.ts\";\nexport * from \"./FileSystem.Types.ts\";\n", "/**\n * @file FileSystem.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nimport { basename, dirname, extname, join } from \"path\";\nimport { type FFileExtension } from \"./FileSystem.Types.ts\";\nimport { type FileHandle } from \"fs/promises\";\nimport { promises as Fs } from \"fs\";\nimport { constants as FsConstants } from \"fs\";\nimport os from \"os\";\nasync function PathExists(Path: string): Promise<boolean> {\n try {\n await Fs.access(Path, FsConstants.F_OK);\n return true;\n }\n catch {\n return false;\n }\n}\n/**\n * @param Extension - The file extension that you wish to test.\n * @returns Whether the file extension is valid on the current platform.\n */\nexport function IsSupportedFileExtension(Extension: FFileExtension): boolean {\n let NormalizedExtension: string = Extension.slice(1);\n if (NormalizedExtension.startsWith(\".\")) {\n NormalizedExtension = NormalizedExtension.slice(1);\n }\n if (NormalizedExtension.length === 0) {\n return false;\n }\n if (NormalizedExtension.includes(\"/\")\n || NormalizedExtension.includes(\"\\\\\")\n || NormalizedExtension.includes(\"\\0\")) {\n return false;\n }\n if (os.platform() === \"win32\") {\n /* eslint-disable-next-line no-control-regex */\n const HasIllegalCharacters: boolean = /[<>:\"/\\\\|?*\\x00-\\x1F]/u.test(NormalizedExtension);\n if (HasIllegalCharacters) {\n return false;\n }\n if (/[ .]$/u.test(NormalizedExtension)) {\n return false;\n }\n }\n return true;\n}\n/**\n * Given a path at which we wish to create a new file, check if a file at that\n * path already exists, and if so, then append `(${ number })` before the file\n * extension, consistent with the Windows Explorer handles conflicting file\n * names when pasting files.\n */\nexport async function GetSafeNewPath(InPath: string): Promise<string> {\n const DirectoryPath: string = dirname(InPath);\n const Extension: string = extname(InPath);\n const FileName: string = basename(InPath);\n const BaseFileName: string = Extension === \"\"\n ? FileName\n : basename(InPath, Extension);\n let CandidatePath: string = InPath;\n let Index: number = 1;\n while (await PathExists(CandidatePath)) {\n const CandidateFileName: string = `${BaseFileName} (${Index})${Extension}`;\n CandidatePath = join(DirectoryPath, CandidateFileName);\n Index++;\n }\n return CandidatePath;\n}\n/**\n * @param DirectoryPath - The path to the directory in which you wish to check.\n * @param FileName - The desired file name.\n * @param PersistNewFile - *(Optional)* Whether to keep the otherwise-temporary\n * file created at the desired path.\n * @param Extension - *(Optional)* If provided, the function will only return `true`\n * if `FileName.endsWith(Extension)` *and* the `Extension` is a valid\n * file extension.\n * @returns Whether a file of the given `FileName` can be created in `DirectoryPath`.\n *\n * @remarks This *does* attempt to create a file at the desired path. The file is\n * temporary iff `!PersistNewFile`, and is never created when this function\n * returns `false`.\n */\nexport async function IsValidFileName(DirectoryPath: string, FileName: string, PersistNewFile: boolean = false, Extension: FFileExtension | undefined = undefined): Promise<boolean> {\n const ExtensionSafe: FFileExtension | null | \"\" = Extension !== undefined\n ? (Extension.startsWith(\".\") && IsSupportedFileExtension(Extension))\n ? Extension\n : null\n : \"\";\n const IsExtensionImproper: boolean = (ExtensionSafe === null ||\n ExtensionSafe === \".\" ||\n !FileName.endsWith(ExtensionSafe));\n if (IsExtensionImproper) {\n return false;\n }\n const FilePath: string = join(DirectoryPath, FileName);\n try {\n const ThisFileHandle: FileHandle = await Fs.open(FilePath, \"wx\");\n await ThisFileHandle.close();\n if (!PersistNewFile) {\n await Fs.unlink(FilePath);\n }\n return true;\n }\n catch {\n return false;\n }\n}\n/**\n * Write a text file to a given {@link Path} having contents {@link Contents}.\n *\n * @param Path - The path of the file that will be written.\n * @param Contents - The text contents of the file to write.\n *\n * @returns {Promise<void>} A {@link Promise} that resolves when the call to {@link Fs.writeFile} resolves.\n *\n * @example\n * ```typescript\n * import { WriteTextFile } from \"@sorrell/utilities/fs\";\n * import { resolve } from \"path\";\n *\n * const MyReadMe: string = \"# ReadMe\\n\\nThis package accomplishes...\\n\";\n * const MyReadMePath: string = resolve(\".\");\n *\n * await WriteTextFile(MyReadMePath, MyReadMe);\n * ```\n */\nexport async function WriteTextFile(Path: string, Contents: string): Promise<void> {\n await Fs.writeFile(Path, Contents, { encoding: \"utf-8\" });\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACMA,kBAAiD;AAGjD,gBAA+B;AAC/B,IAAAA,aAAyC;AACzC,gBAAe;
|
|
6
|
-
"names": ["import_fs", "Fs", "FsConstants", "os"]
|
|
4
|
+
"sourcesContent": ["/**\n * @file index.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nexport * from \"./FileSystem.ts\";\nexport * from \"./FileSystem.Types.ts\";\n", "/**\n * @file FileSystem.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nimport { basename, dirname, extname, join } from \"path\";\nimport { type FFileExtension } from \"./FileSystem.Types.ts\";\nimport { type FileHandle } from \"fs/promises\";\nimport { promises as Fs } from \"fs\";\nimport { constants as FsConstants } from \"fs\";\nimport os from \"os\";\nasync function PathExists(Path: string): Promise<boolean> {\n try {\n await Fs.access(Path, FsConstants.F_OK);\n return true;\n }\n catch {\n return false;\n }\n}\n/**\n * @param Extension - The file extension that you wish to test.\n * @returns Whether the file extension is valid on the current platform.\n */\nexport function IsSupportedFileExtension(Extension: FFileExtension): boolean {\n let NormalizedExtension: string = Extension.slice(1);\n if (NormalizedExtension.startsWith(\".\")) {\n NormalizedExtension = NormalizedExtension.slice(1);\n }\n if (NormalizedExtension.length === 0) {\n return false;\n }\n if (NormalizedExtension.includes(\"/\")\n || NormalizedExtension.includes(\"\\\\\")\n || NormalizedExtension.includes(\"\\0\")) {\n return false;\n }\n if (os.platform() === \"win32\") {\n /* eslint-disable-next-line no-control-regex */\n const HasIllegalCharacters: boolean = /[<>:\"/\\\\|?*\\x00-\\x1F]/u.test(NormalizedExtension);\n if (HasIllegalCharacters) {\n return false;\n }\n if (/[ .]$/u.test(NormalizedExtension)) {\n return false;\n }\n }\n return true;\n}\n/**\n * Given a path at which we wish to create a new file, check if a file at that\n * path already exists, and if so, then append `(${ number })` before the file\n * extension, consistent with the Windows Explorer handles conflicting file\n * names when pasting files.\n */\nexport async function GetSafeNewPath(InPath: string): Promise<string> {\n const DirectoryPath: string = dirname(InPath);\n const Extension: string = extname(InPath);\n const FileName: string = basename(InPath);\n const BaseFileName: string = Extension === \"\"\n ? FileName\n : basename(InPath, Extension);\n let CandidatePath: string = InPath;\n let Index: number = 1;\n while (await PathExists(CandidatePath)) {\n const CandidateFileName: string = `${BaseFileName} (${Index})${Extension}`;\n CandidatePath = join(DirectoryPath, CandidateFileName);\n Index++;\n }\n return CandidatePath;\n}\n/**\n * @param DirectoryPath - The path to the directory in which you wish to check.\n * @param FileName - The desired file name.\n * @param PersistNewFile - *(Optional)* Whether to keep the otherwise-temporary\n * file created at the desired path.\n * @param Extension - *(Optional)* If provided, the function will only return `true`\n * if `FileName.endsWith(Extension)` *and* the `Extension` is a valid\n * file extension.\n * @returns Whether a file of the given `FileName` can be created in `DirectoryPath`.\n *\n * @remarks This *does* attempt to create a file at the desired path. The file is\n * temporary iff `!PersistNewFile`, and is never created when this function\n * returns `false`.\n */\nexport async function IsValidFileName(DirectoryPath: string, FileName: string, PersistNewFile: boolean = false, Extension: FFileExtension | undefined = undefined): Promise<boolean> {\n const ExtensionSafe: FFileExtension | null | \"\" = Extension !== undefined\n ? (Extension.startsWith(\".\") && IsSupportedFileExtension(Extension))\n ? Extension\n : null\n : \"\";\n const IsExtensionImproper: boolean = (ExtensionSafe === null ||\n ExtensionSafe === \".\" ||\n !FileName.endsWith(ExtensionSafe));\n if (IsExtensionImproper) {\n return false;\n }\n const FilePath: string = join(DirectoryPath, FileName);\n try {\n const ThisFileHandle: FileHandle = await Fs.open(FilePath, \"wx\");\n await ThisFileHandle.close();\n if (!PersistNewFile) {\n await Fs.unlink(FilePath);\n }\n return true;\n }\n catch {\n return false;\n }\n}\n/**\n * Write a text file to a given {@link Path} having contents {@link Contents}.\n *\n * @param Path - The path of the file that will be written.\n * @param Contents - The text contents of the file to write.\n *\n * @returns {Promise<void>} A {@link Promise} that resolves when the call to {@link Fs.writeFile} resolves.\n *\n * @example\n * ```typescript\n * import { WriteTextFile } from \"@sorrell/utilities/fs\";\n * import { resolve } from \"path\";\n *\n * const MyReadMe: string = \"# ReadMe\\n\\nThis package accomplishes...\\n\";\n * const MyReadMePath: string = resolve(\".\");\n *\n * await WriteTextFile(MyReadMePath, MyReadMe);\n * ```\n */\nexport async function WriteTextFile(Path: string, Contents: string): Promise<void> {\n await Fs.writeFile(Path, Contents, { encoding: \"utf-8\" });\n}\nimport * as FileSystem from \"node:fs/promises\";\nimport * as Path from \"node:path\";\nimport * as Readline from \"node:readline\";\ntype DeletePhase = \"Scanning\" | \"Deleting\" | \"Done\";\ntype DeleteEntryKind = \"File\" | \"Directory\" | \"Other\";\ntype DeleteEntry = {\n EntryPath: string;\n Kind: DeleteEntryKind;\n Size: number;\n};\ntype DeleteProgress = {\n Phase: DeletePhase;\n CurrentPath: string | null;\n DiscoveredEntries: number;\n TotalEntries: number;\n DeletedEntries: number;\n TotalBytes: number;\n DeletedBytes: number;\n};\ntype DeleteWithProgressOptions = {\n OnProgress?: (Progress: DeleteProgress) => void;\n Signal?: AbortSignal;\n};\nfunction IsMissingFileError(ErrorValue: unknown): boolean {\n return (typeof ErrorValue === \"object\" &&\n ErrorValue !== null &&\n \"code\" in ErrorValue &&\n ErrorValue.code === \"ENOENT\");\n}\nfunction CloneProgress(Progress: DeleteProgress): DeleteProgress {\n return { ...Progress };\n}\nasync function BuildDeletionPlan(RootPath: string, Progress: DeleteProgress, Options: DeleteWithProgressOptions): Promise<DeleteEntry[]> {\n const Entries: DeleteEntry[] = [];\n async function Visit(CurrentPath: string): Promise<void> {\n Options.Signal?.throwIfAborted();\n Progress.Phase = \"Scanning\";\n Progress.CurrentPath = CurrentPath;\n Options.OnProgress?.(CloneProgress(Progress));\n let Stats;\n try {\n Stats = await FileSystem.lstat(CurrentPath);\n }\n catch (ErrorValue) {\n if (IsMissingFileError(ErrorValue)) {\n return;\n }\n throw ErrorValue;\n }\n if (Stats.isDirectory()) {\n const Children = await FileSystem.readdir(CurrentPath, {\n withFileTypes: true\n });\n for (const Child of Children) {\n await Visit(Path.join(CurrentPath, Child.name));\n }\n Entries.push({\n EntryPath: CurrentPath,\n Kind: \"Directory\",\n Size: 0\n });\n }\n else {\n const Size = Stats.isFile() ? Stats.size : 0;\n Entries.push({\n EntryPath: CurrentPath,\n Kind: Stats.isFile() ? \"File\" : \"Other\",\n Size\n });\n Progress.TotalBytes += Size;\n }\n Progress.DiscoveredEntries = Entries.length;\n Options.OnProgress?.(CloneProgress(Progress));\n }\n await Visit(RootPath);\n return Entries;\n}\nexport async function DeleteWithProgress(RootPath: string, Options: DeleteWithProgressOptions = {}): Promise<void> {\n const Progress: DeleteProgress = {\n Phase: \"Scanning\",\n CurrentPath: null,\n DiscoveredEntries: 0,\n TotalEntries: 0,\n DeletedEntries: 0,\n TotalBytes: 0,\n DeletedBytes: 0\n };\n const Entries = await BuildDeletionPlan(RootPath, Progress, Options);\n Progress.Phase = \"Deleting\";\n Progress.TotalEntries = Entries.length;\n Progress.CurrentPath = null;\n Options.OnProgress?.(CloneProgress(Progress));\n for (const Entry of Entries) {\n Options.Signal?.throwIfAborted();\n Progress.CurrentPath = Entry.EntryPath;\n Options.OnProgress?.(CloneProgress(Progress));\n try {\n if (Entry.Kind === \"Directory\") {\n await FileSystem.rmdir(Entry.EntryPath);\n }\n else {\n await FileSystem.unlink(Entry.EntryPath);\n }\n }\n catch (ErrorValue) {\n if (!IsMissingFileError(ErrorValue)) {\n throw ErrorValue;\n }\n }\n Progress.DeletedEntries += 1;\n Progress.DeletedBytes += Entry.Size;\n Options.OnProgress?.(CloneProgress(Progress));\n }\n Progress.Phase = \"Done\";\n Progress.CurrentPath = null;\n Options.OnProgress?.(CloneProgress(Progress));\n}\nfunction FormatBytes(Bytes: number): string {\n const Units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n let Value = Bytes;\n let UnitIndex = 0;\n while (Value >= 1024 && UnitIndex < Units.length - 1) {\n Value /= 1024;\n UnitIndex += 1;\n }\n return `${Value.toFixed(UnitIndex === 0 ? 0 : 1)} ${Units[UnitIndex]}`;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_fs", "Path", "Fs", "FsConstants", "os"]
|
|
7
7
|
}
|
package/Distribution/fs.js
CHANGED
|
@@ -3,9 +3,11 @@ import { basename, dirname, extname, join } from "path";
|
|
|
3
3
|
import { promises as Fs } from "fs";
|
|
4
4
|
import { constants as FsConstants } from "fs";
|
|
5
5
|
import os from "os";
|
|
6
|
-
|
|
6
|
+
import * as FileSystem from "node:fs/promises";
|
|
7
|
+
import * as Path from "node:path";
|
|
8
|
+
async function PathExists(Path2) {
|
|
7
9
|
try {
|
|
8
|
-
await Fs.access(
|
|
10
|
+
await Fs.access(Path2, FsConstants.F_OK);
|
|
9
11
|
return true;
|
|
10
12
|
} catch {
|
|
11
13
|
return false;
|
|
@@ -65,10 +67,98 @@ async function IsValidFileName(DirectoryPath, FileName, PersistNewFile = false,
|
|
|
65
67
|
return false;
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
|
-
async function WriteTextFile(
|
|
69
|
-
await Fs.writeFile(
|
|
70
|
+
async function WriteTextFile(Path2, Contents) {
|
|
71
|
+
await Fs.writeFile(Path2, Contents, { encoding: "utf-8" });
|
|
72
|
+
}
|
|
73
|
+
function IsMissingFileError(ErrorValue) {
|
|
74
|
+
return typeof ErrorValue === "object" && ErrorValue !== null && "code" in ErrorValue && ErrorValue.code === "ENOENT";
|
|
75
|
+
}
|
|
76
|
+
function CloneProgress(Progress) {
|
|
77
|
+
return { ...Progress };
|
|
78
|
+
}
|
|
79
|
+
async function BuildDeletionPlan(RootPath, Progress, Options) {
|
|
80
|
+
const Entries = [];
|
|
81
|
+
async function Visit(CurrentPath) {
|
|
82
|
+
Options.Signal?.throwIfAborted();
|
|
83
|
+
Progress.Phase = "Scanning";
|
|
84
|
+
Progress.CurrentPath = CurrentPath;
|
|
85
|
+
Options.OnProgress?.(CloneProgress(Progress));
|
|
86
|
+
let Stats;
|
|
87
|
+
try {
|
|
88
|
+
Stats = await FileSystem.lstat(CurrentPath);
|
|
89
|
+
} catch (ErrorValue) {
|
|
90
|
+
if (IsMissingFileError(ErrorValue)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
throw ErrorValue;
|
|
94
|
+
}
|
|
95
|
+
if (Stats.isDirectory()) {
|
|
96
|
+
const Children = await FileSystem.readdir(CurrentPath, {
|
|
97
|
+
withFileTypes: true
|
|
98
|
+
});
|
|
99
|
+
for (const Child of Children) {
|
|
100
|
+
await Visit(Path.join(CurrentPath, Child.name));
|
|
101
|
+
}
|
|
102
|
+
Entries.push({
|
|
103
|
+
EntryPath: CurrentPath,
|
|
104
|
+
Kind: "Directory",
|
|
105
|
+
Size: 0
|
|
106
|
+
});
|
|
107
|
+
} else {
|
|
108
|
+
const Size = Stats.isFile() ? Stats.size : 0;
|
|
109
|
+
Entries.push({
|
|
110
|
+
EntryPath: CurrentPath,
|
|
111
|
+
Kind: Stats.isFile() ? "File" : "Other",
|
|
112
|
+
Size
|
|
113
|
+
});
|
|
114
|
+
Progress.TotalBytes += Size;
|
|
115
|
+
}
|
|
116
|
+
Progress.DiscoveredEntries = Entries.length;
|
|
117
|
+
Options.OnProgress?.(CloneProgress(Progress));
|
|
118
|
+
}
|
|
119
|
+
await Visit(RootPath);
|
|
120
|
+
return Entries;
|
|
121
|
+
}
|
|
122
|
+
async function DeleteWithProgress(RootPath, Options = {}) {
|
|
123
|
+
const Progress = {
|
|
124
|
+
Phase: "Scanning",
|
|
125
|
+
CurrentPath: null,
|
|
126
|
+
DiscoveredEntries: 0,
|
|
127
|
+
TotalEntries: 0,
|
|
128
|
+
DeletedEntries: 0,
|
|
129
|
+
TotalBytes: 0,
|
|
130
|
+
DeletedBytes: 0
|
|
131
|
+
};
|
|
132
|
+
const Entries = await BuildDeletionPlan(RootPath, Progress, Options);
|
|
133
|
+
Progress.Phase = "Deleting";
|
|
134
|
+
Progress.TotalEntries = Entries.length;
|
|
135
|
+
Progress.CurrentPath = null;
|
|
136
|
+
Options.OnProgress?.(CloneProgress(Progress));
|
|
137
|
+
for (const Entry of Entries) {
|
|
138
|
+
Options.Signal?.throwIfAborted();
|
|
139
|
+
Progress.CurrentPath = Entry.EntryPath;
|
|
140
|
+
Options.OnProgress?.(CloneProgress(Progress));
|
|
141
|
+
try {
|
|
142
|
+
if (Entry.Kind === "Directory") {
|
|
143
|
+
await FileSystem.rmdir(Entry.EntryPath);
|
|
144
|
+
} else {
|
|
145
|
+
await FileSystem.unlink(Entry.EntryPath);
|
|
146
|
+
}
|
|
147
|
+
} catch (ErrorValue) {
|
|
148
|
+
if (!IsMissingFileError(ErrorValue)) {
|
|
149
|
+
throw ErrorValue;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
Progress.DeletedEntries += 1;
|
|
153
|
+
Progress.DeletedBytes += Entry.Size;
|
|
154
|
+
Options.OnProgress?.(CloneProgress(Progress));
|
|
155
|
+
}
|
|
156
|
+
Progress.Phase = "Done";
|
|
157
|
+
Progress.CurrentPath = null;
|
|
158
|
+
Options.OnProgress?.(CloneProgress(Progress));
|
|
70
159
|
}
|
|
71
160
|
export {
|
|
161
|
+
DeleteWithProgress,
|
|
72
162
|
GetSafeNewPath,
|
|
73
163
|
IsSupportedFileExtension,
|
|
74
164
|
IsValidFileName,
|
package/Distribution/fs.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../Source/FileSystem/FileSystem.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @file FileSystem.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nimport { basename, dirname, extname, join } from \"path\";\nimport { type FFileExtension } from \"./FileSystem.Types.ts\";\nimport { type FileHandle } from \"fs/promises\";\nimport { promises as Fs } from \"fs\";\nimport { constants as FsConstants } from \"fs\";\nimport os from \"os\";\nasync function PathExists(Path: string): Promise<boolean> {\n try {\n await Fs.access(Path, FsConstants.F_OK);\n return true;\n }\n catch {\n return false;\n }\n}\n/**\n * @param Extension - The file extension that you wish to test.\n * @returns Whether the file extension is valid on the current platform.\n */\nexport function IsSupportedFileExtension(Extension: FFileExtension): boolean {\n let NormalizedExtension: string = Extension.slice(1);\n if (NormalizedExtension.startsWith(\".\")) {\n NormalizedExtension = NormalizedExtension.slice(1);\n }\n if (NormalizedExtension.length === 0) {\n return false;\n }\n if (NormalizedExtension.includes(\"/\")\n || NormalizedExtension.includes(\"\\\\\")\n || NormalizedExtension.includes(\"\\0\")) {\n return false;\n }\n if (os.platform() === \"win32\") {\n /* eslint-disable-next-line no-control-regex */\n const HasIllegalCharacters: boolean = /[<>:\"/\\\\|?*\\x00-\\x1F]/u.test(NormalizedExtension);\n if (HasIllegalCharacters) {\n return false;\n }\n if (/[ .]$/u.test(NormalizedExtension)) {\n return false;\n }\n }\n return true;\n}\n/**\n * Given a path at which we wish to create a new file, check if a file at that\n * path already exists, and if so, then append `(${ number })` before the file\n * extension, consistent with the Windows Explorer handles conflicting file\n * names when pasting files.\n */\nexport async function GetSafeNewPath(InPath: string): Promise<string> {\n const DirectoryPath: string = dirname(InPath);\n const Extension: string = extname(InPath);\n const FileName: string = basename(InPath);\n const BaseFileName: string = Extension === \"\"\n ? FileName\n : basename(InPath, Extension);\n let CandidatePath: string = InPath;\n let Index: number = 1;\n while (await PathExists(CandidatePath)) {\n const CandidateFileName: string = `${BaseFileName} (${Index})${Extension}`;\n CandidatePath = join(DirectoryPath, CandidateFileName);\n Index++;\n }\n return CandidatePath;\n}\n/**\n * @param DirectoryPath - The path to the directory in which you wish to check.\n * @param FileName - The desired file name.\n * @param PersistNewFile - *(Optional)* Whether to keep the otherwise-temporary\n * file created at the desired path.\n * @param Extension - *(Optional)* If provided, the function will only return `true`\n * if `FileName.endsWith(Extension)` *and* the `Extension` is a valid\n * file extension.\n * @returns Whether a file of the given `FileName` can be created in `DirectoryPath`.\n *\n * @remarks This *does* attempt to create a file at the desired path. The file is\n * temporary iff `!PersistNewFile`, and is never created when this function\n * returns `false`.\n */\nexport async function IsValidFileName(DirectoryPath: string, FileName: string, PersistNewFile: boolean = false, Extension: FFileExtension | undefined = undefined): Promise<boolean> {\n const ExtensionSafe: FFileExtension | null | \"\" = Extension !== undefined\n ? (Extension.startsWith(\".\") && IsSupportedFileExtension(Extension))\n ? Extension\n : null\n : \"\";\n const IsExtensionImproper: boolean = (ExtensionSafe === null ||\n ExtensionSafe === \".\" ||\n !FileName.endsWith(ExtensionSafe));\n if (IsExtensionImproper) {\n return false;\n }\n const FilePath: string = join(DirectoryPath, FileName);\n try {\n const ThisFileHandle: FileHandle = await Fs.open(FilePath, \"wx\");\n await ThisFileHandle.close();\n if (!PersistNewFile) {\n await Fs.unlink(FilePath);\n }\n return true;\n }\n catch {\n return false;\n }\n}\n/**\n * Write a text file to a given {@link Path} having contents {@link Contents}.\n *\n * @param Path - The path of the file that will be written.\n * @param Contents - The text contents of the file to write.\n *\n * @returns {Promise<void>} A {@link Promise} that resolves when the call to {@link Fs.writeFile} resolves.\n *\n * @example\n * ```typescript\n * import { WriteTextFile } from \"@sorrell/utilities/fs\";\n * import { resolve } from \"path\";\n *\n * const MyReadMe: string = \"# ReadMe\\n\\nThis package accomplishes...\\n\";\n * const MyReadMePath: string = resolve(\".\");\n *\n * await WriteTextFile(MyReadMePath, MyReadMe);\n * ```\n */\nexport async function WriteTextFile(Path: string, Contents: string): Promise<void> {\n await Fs.writeFile(Path, Contents, { encoding: \"utf-8\" });\n}\n"],
|
|
5
|
-
"mappings": ";AAMA,SAAS,UAAU,SAAS,SAAS,YAAY;AAGjD,SAAS,YAAY,UAAU;AAC/B,SAAS,aAAa,mBAAmB;AACzC,OAAO,QAAQ;
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["/**\n * @file FileSystem.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nimport { basename, dirname, extname, join } from \"path\";\nimport { type FFileExtension } from \"./FileSystem.Types.ts\";\nimport { type FileHandle } from \"fs/promises\";\nimport { promises as Fs } from \"fs\";\nimport { constants as FsConstants } from \"fs\";\nimport os from \"os\";\nasync function PathExists(Path: string): Promise<boolean> {\n try {\n await Fs.access(Path, FsConstants.F_OK);\n return true;\n }\n catch {\n return false;\n }\n}\n/**\n * @param Extension - The file extension that you wish to test.\n * @returns Whether the file extension is valid on the current platform.\n */\nexport function IsSupportedFileExtension(Extension: FFileExtension): boolean {\n let NormalizedExtension: string = Extension.slice(1);\n if (NormalizedExtension.startsWith(\".\")) {\n NormalizedExtension = NormalizedExtension.slice(1);\n }\n if (NormalizedExtension.length === 0) {\n return false;\n }\n if (NormalizedExtension.includes(\"/\")\n || NormalizedExtension.includes(\"\\\\\")\n || NormalizedExtension.includes(\"\\0\")) {\n return false;\n }\n if (os.platform() === \"win32\") {\n /* eslint-disable-next-line no-control-regex */\n const HasIllegalCharacters: boolean = /[<>:\"/\\\\|?*\\x00-\\x1F]/u.test(NormalizedExtension);\n if (HasIllegalCharacters) {\n return false;\n }\n if (/[ .]$/u.test(NormalizedExtension)) {\n return false;\n }\n }\n return true;\n}\n/**\n * Given a path at which we wish to create a new file, check if a file at that\n * path already exists, and if so, then append `(${ number })` before the file\n * extension, consistent with the Windows Explorer handles conflicting file\n * names when pasting files.\n */\nexport async function GetSafeNewPath(InPath: string): Promise<string> {\n const DirectoryPath: string = dirname(InPath);\n const Extension: string = extname(InPath);\n const FileName: string = basename(InPath);\n const BaseFileName: string = Extension === \"\"\n ? FileName\n : basename(InPath, Extension);\n let CandidatePath: string = InPath;\n let Index: number = 1;\n while (await PathExists(CandidatePath)) {\n const CandidateFileName: string = `${BaseFileName} (${Index})${Extension}`;\n CandidatePath = join(DirectoryPath, CandidateFileName);\n Index++;\n }\n return CandidatePath;\n}\n/**\n * @param DirectoryPath - The path to the directory in which you wish to check.\n * @param FileName - The desired file name.\n * @param PersistNewFile - *(Optional)* Whether to keep the otherwise-temporary\n * file created at the desired path.\n * @param Extension - *(Optional)* If provided, the function will only return `true`\n * if `FileName.endsWith(Extension)` *and* the `Extension` is a valid\n * file extension.\n * @returns Whether a file of the given `FileName` can be created in `DirectoryPath`.\n *\n * @remarks This *does* attempt to create a file at the desired path. The file is\n * temporary iff `!PersistNewFile`, and is never created when this function\n * returns `false`.\n */\nexport async function IsValidFileName(DirectoryPath: string, FileName: string, PersistNewFile: boolean = false, Extension: FFileExtension | undefined = undefined): Promise<boolean> {\n const ExtensionSafe: FFileExtension | null | \"\" = Extension !== undefined\n ? (Extension.startsWith(\".\") && IsSupportedFileExtension(Extension))\n ? Extension\n : null\n : \"\";\n const IsExtensionImproper: boolean = (ExtensionSafe === null ||\n ExtensionSafe === \".\" ||\n !FileName.endsWith(ExtensionSafe));\n if (IsExtensionImproper) {\n return false;\n }\n const FilePath: string = join(DirectoryPath, FileName);\n try {\n const ThisFileHandle: FileHandle = await Fs.open(FilePath, \"wx\");\n await ThisFileHandle.close();\n if (!PersistNewFile) {\n await Fs.unlink(FilePath);\n }\n return true;\n }\n catch {\n return false;\n }\n}\n/**\n * Write a text file to a given {@link Path} having contents {@link Contents}.\n *\n * @param Path - The path of the file that will be written.\n * @param Contents - The text contents of the file to write.\n *\n * @returns {Promise<void>} A {@link Promise} that resolves when the call to {@link Fs.writeFile} resolves.\n *\n * @example\n * ```typescript\n * import { WriteTextFile } from \"@sorrell/utilities/fs\";\n * import { resolve } from \"path\";\n *\n * const MyReadMe: string = \"# ReadMe\\n\\nThis package accomplishes...\\n\";\n * const MyReadMePath: string = resolve(\".\");\n *\n * await WriteTextFile(MyReadMePath, MyReadMe);\n * ```\n */\nexport async function WriteTextFile(Path: string, Contents: string): Promise<void> {\n await Fs.writeFile(Path, Contents, { encoding: \"utf-8\" });\n}\nimport * as FileSystem from \"node:fs/promises\";\nimport * as Path from \"node:path\";\nimport * as Readline from \"node:readline\";\ntype DeletePhase = \"Scanning\" | \"Deleting\" | \"Done\";\ntype DeleteEntryKind = \"File\" | \"Directory\" | \"Other\";\ntype DeleteEntry = {\n EntryPath: string;\n Kind: DeleteEntryKind;\n Size: number;\n};\ntype DeleteProgress = {\n Phase: DeletePhase;\n CurrentPath: string | null;\n DiscoveredEntries: number;\n TotalEntries: number;\n DeletedEntries: number;\n TotalBytes: number;\n DeletedBytes: number;\n};\ntype DeleteWithProgressOptions = {\n OnProgress?: (Progress: DeleteProgress) => void;\n Signal?: AbortSignal;\n};\nfunction IsMissingFileError(ErrorValue: unknown): boolean {\n return (typeof ErrorValue === \"object\" &&\n ErrorValue !== null &&\n \"code\" in ErrorValue &&\n ErrorValue.code === \"ENOENT\");\n}\nfunction CloneProgress(Progress: DeleteProgress): DeleteProgress {\n return { ...Progress };\n}\nasync function BuildDeletionPlan(RootPath: string, Progress: DeleteProgress, Options: DeleteWithProgressOptions): Promise<DeleteEntry[]> {\n const Entries: DeleteEntry[] = [];\n async function Visit(CurrentPath: string): Promise<void> {\n Options.Signal?.throwIfAborted();\n Progress.Phase = \"Scanning\";\n Progress.CurrentPath = CurrentPath;\n Options.OnProgress?.(CloneProgress(Progress));\n let Stats;\n try {\n Stats = await FileSystem.lstat(CurrentPath);\n }\n catch (ErrorValue) {\n if (IsMissingFileError(ErrorValue)) {\n return;\n }\n throw ErrorValue;\n }\n if (Stats.isDirectory()) {\n const Children = await FileSystem.readdir(CurrentPath, {\n withFileTypes: true\n });\n for (const Child of Children) {\n await Visit(Path.join(CurrentPath, Child.name));\n }\n Entries.push({\n EntryPath: CurrentPath,\n Kind: \"Directory\",\n Size: 0\n });\n }\n else {\n const Size = Stats.isFile() ? Stats.size : 0;\n Entries.push({\n EntryPath: CurrentPath,\n Kind: Stats.isFile() ? \"File\" : \"Other\",\n Size\n });\n Progress.TotalBytes += Size;\n }\n Progress.DiscoveredEntries = Entries.length;\n Options.OnProgress?.(CloneProgress(Progress));\n }\n await Visit(RootPath);\n return Entries;\n}\nexport async function DeleteWithProgress(RootPath: string, Options: DeleteWithProgressOptions = {}): Promise<void> {\n const Progress: DeleteProgress = {\n Phase: \"Scanning\",\n CurrentPath: null,\n DiscoveredEntries: 0,\n TotalEntries: 0,\n DeletedEntries: 0,\n TotalBytes: 0,\n DeletedBytes: 0\n };\n const Entries = await BuildDeletionPlan(RootPath, Progress, Options);\n Progress.Phase = \"Deleting\";\n Progress.TotalEntries = Entries.length;\n Progress.CurrentPath = null;\n Options.OnProgress?.(CloneProgress(Progress));\n for (const Entry of Entries) {\n Options.Signal?.throwIfAborted();\n Progress.CurrentPath = Entry.EntryPath;\n Options.OnProgress?.(CloneProgress(Progress));\n try {\n if (Entry.Kind === \"Directory\") {\n await FileSystem.rmdir(Entry.EntryPath);\n }\n else {\n await FileSystem.unlink(Entry.EntryPath);\n }\n }\n catch (ErrorValue) {\n if (!IsMissingFileError(ErrorValue)) {\n throw ErrorValue;\n }\n }\n Progress.DeletedEntries += 1;\n Progress.DeletedBytes += Entry.Size;\n Options.OnProgress?.(CloneProgress(Progress));\n }\n Progress.Phase = \"Done\";\n Progress.CurrentPath = null;\n Options.OnProgress?.(CloneProgress(Progress));\n}\nfunction FormatBytes(Bytes: number): string {\n const Units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n let Value = Bytes;\n let UnitIndex = 0;\n while (Value >= 1024 && UnitIndex < Units.length - 1) {\n Value /= 1024;\n UnitIndex += 1;\n }\n return `${Value.toFixed(UnitIndex === 0 ? 0 : 1)} ${Units[UnitIndex]}`;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Path"]
|
|
7
7
|
}
|
|
@@ -25,8 +25,8 @@ __export(Functional_exports, {
|
|
|
25
25
|
module.exports = __toCommonJS(Functional_exports);
|
|
26
26
|
|
|
27
27
|
// Source/Functional/Functional.ts
|
|
28
|
-
function Identity(...
|
|
29
|
-
return
|
|
28
|
+
function Identity(...ArgumentVector) {
|
|
29
|
+
return ArgumentVector;
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* @file Functional.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../Source/Functional/index.ts", "../Source/Functional/Functional.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @file index.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nexport * from \"./Functional.ts\";\nexport * from \"./Functional.Types.ts\";\n", "/**\n * @file Functional.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;
|
|
4
|
+
"sourcesContent": ["/**\n * @file index.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nexport * from \"./Functional.ts\";\nexport * from \"./Functional.Types.ts\";\n", "/**\n * @file Functional.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\n/* eslint-disable jsdoc/require-example */\n/**\n * The identity mapping, for some {@link Array} of {@link ArgumentVector | given arguments}.\n *\n * @param ArgumentVector - The {@link Array} of given arguments.\n * @returns {typeof ArgumentVector} The {@link Array} of given arguments.\n */\nexport function Identity<ArgumentType>(...ArgumentVector: Array<ArgumentType>): typeof ArgumentVector {\n return ArgumentVector;\n}\n/* eslint-enable jsdoc/require-example */\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACaO,SAAS,YAA0B,gBAA4D;AAClG,SAAO;AACX;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../Source/Functional/Functional.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @file Functional.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["/**\n * @file Functional.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\n/* eslint-disable jsdoc/require-example */\n/**\n * The identity mapping, for some {@link Array} of {@link ArgumentVector | given arguments}.\n *\n * @param ArgumentVector - The {@link Array} of given arguments.\n * @returns {typeof ArgumentVector} The {@link Array} of given arguments.\n */\nexport function Identity<ArgumentType>(...ArgumentVector: Array<ArgumentType>): typeof ArgumentVector {\n return ArgumentVector;\n}\n/* eslint-enable jsdoc/require-example */\n"],
|
|
5
|
+
"mappings": ";AAaO,SAAS,YAA0B,gBAA4D;AAClG,SAAO;AACX;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
|
|
16
|
+
// Source/HigherKind/index.ts
|
|
17
|
+
var HigherKind_exports = {};
|
|
18
|
+
module.exports = __toCommonJS(HigherKind_exports);
|
|
19
|
+
/**
|
|
20
|
+
* @file HigherKind.Types.ts
|
|
21
|
+
* @author Gage Sorrell <gage@sorrell.sh>
|
|
22
|
+
* @copyright (c) 2026 Gage Sorrell
|
|
23
|
+
* @license MIT
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* @file index.ts
|
|
27
|
+
* @author Gage Sorrell <gage@sorrell.sh>
|
|
28
|
+
* @copyright (c) 2026 Gage Sorrell
|
|
29
|
+
* @license MIT
|
|
30
|
+
*/
|
|
31
|
+
//# sourceMappingURL=higher-kind.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../Source/HigherKind/index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * @file index.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nexport * from \"./HigherKind.Types.ts\";\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file HigherKind.Types.ts
|
|
3
|
+
* @author Gage Sorrell <gage@sorrell.sh>
|
|
4
|
+
* @copyright (c) 2026 Gage Sorrell
|
|
5
|
+
* @license MIT
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* @file index.ts
|
|
9
|
+
* @author Gage Sorrell <gage@sorrell.sh>
|
|
10
|
+
* @copyright (c) 2026 Gage Sorrell
|
|
11
|
+
* @license MIT
|
|
12
|
+
*/
|
|
13
|
+
//# sourceMappingURL=higher-kind.js.map
|
package/Distribution/index.cjs
CHANGED
|
@@ -39,7 +39,8 @@ __export(Source_exports, {
|
|
|
39
39
|
Miscellaneous: () => Miscellaneous_exports,
|
|
40
40
|
Npm: () => Npm_exports,
|
|
41
41
|
Path: () => Path_exports,
|
|
42
|
-
String: () => String_exports
|
|
42
|
+
String: () => String_exports,
|
|
43
|
+
TsConfig: () => TsConfig_exports
|
|
43
44
|
});
|
|
44
45
|
module.exports = __toCommonJS(Source_exports);
|
|
45
46
|
|
|
@@ -254,6 +255,7 @@ var i = new FComplex(0, 1);
|
|
|
254
255
|
// Source/FileSystem/index.ts
|
|
255
256
|
var FileSystem_exports = {};
|
|
256
257
|
__export(FileSystem_exports, {
|
|
258
|
+
DeleteWithProgress: () => DeleteWithProgress,
|
|
257
259
|
GetSafeNewPath: () => GetSafeNewPath,
|
|
258
260
|
IsSupportedFileExtension: () => IsSupportedFileExtension,
|
|
259
261
|
IsValidFileName: () => IsValidFileName,
|
|
@@ -265,9 +267,11 @@ var import_path = require("path");
|
|
|
265
267
|
var import_fs = require("fs");
|
|
266
268
|
var import_fs2 = require("fs");
|
|
267
269
|
var import_os = __toESM(require("os"), 1);
|
|
268
|
-
|
|
270
|
+
var FileSystem = __toESM(require("node:fs/promises"), 1);
|
|
271
|
+
var Path = __toESM(require("node:path"), 1);
|
|
272
|
+
async function PathExists(Path2) {
|
|
269
273
|
try {
|
|
270
|
-
await import_fs.promises.access(
|
|
274
|
+
await import_fs.promises.access(Path2, import_fs2.constants.F_OK);
|
|
271
275
|
return true;
|
|
272
276
|
} catch {
|
|
273
277
|
return false;
|
|
@@ -327,8 +331,95 @@ async function IsValidFileName(DirectoryPath, FileName, PersistNewFile = false,
|
|
|
327
331
|
return false;
|
|
328
332
|
}
|
|
329
333
|
}
|
|
330
|
-
async function WriteTextFile(
|
|
331
|
-
await import_fs.promises.writeFile(
|
|
334
|
+
async function WriteTextFile(Path2, Contents) {
|
|
335
|
+
await import_fs.promises.writeFile(Path2, Contents, { encoding: "utf-8" });
|
|
336
|
+
}
|
|
337
|
+
function IsMissingFileError(ErrorValue) {
|
|
338
|
+
return typeof ErrorValue === "object" && ErrorValue !== null && "code" in ErrorValue && ErrorValue.code === "ENOENT";
|
|
339
|
+
}
|
|
340
|
+
function CloneProgress(Progress) {
|
|
341
|
+
return { ...Progress };
|
|
342
|
+
}
|
|
343
|
+
async function BuildDeletionPlan(RootPath, Progress, Options) {
|
|
344
|
+
const Entries = [];
|
|
345
|
+
async function Visit(CurrentPath) {
|
|
346
|
+
Options.Signal?.throwIfAborted();
|
|
347
|
+
Progress.Phase = "Scanning";
|
|
348
|
+
Progress.CurrentPath = CurrentPath;
|
|
349
|
+
Options.OnProgress?.(CloneProgress(Progress));
|
|
350
|
+
let Stats;
|
|
351
|
+
try {
|
|
352
|
+
Stats = await FileSystem.lstat(CurrentPath);
|
|
353
|
+
} catch (ErrorValue) {
|
|
354
|
+
if (IsMissingFileError(ErrorValue)) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
throw ErrorValue;
|
|
358
|
+
}
|
|
359
|
+
if (Stats.isDirectory()) {
|
|
360
|
+
const Children = await FileSystem.readdir(CurrentPath, {
|
|
361
|
+
withFileTypes: true
|
|
362
|
+
});
|
|
363
|
+
for (const Child of Children) {
|
|
364
|
+
await Visit(Path.join(CurrentPath, Child.name));
|
|
365
|
+
}
|
|
366
|
+
Entries.push({
|
|
367
|
+
EntryPath: CurrentPath,
|
|
368
|
+
Kind: "Directory",
|
|
369
|
+
Size: 0
|
|
370
|
+
});
|
|
371
|
+
} else {
|
|
372
|
+
const Size = Stats.isFile() ? Stats.size : 0;
|
|
373
|
+
Entries.push({
|
|
374
|
+
EntryPath: CurrentPath,
|
|
375
|
+
Kind: Stats.isFile() ? "File" : "Other",
|
|
376
|
+
Size
|
|
377
|
+
});
|
|
378
|
+
Progress.TotalBytes += Size;
|
|
379
|
+
}
|
|
380
|
+
Progress.DiscoveredEntries = Entries.length;
|
|
381
|
+
Options.OnProgress?.(CloneProgress(Progress));
|
|
382
|
+
}
|
|
383
|
+
await Visit(RootPath);
|
|
384
|
+
return Entries;
|
|
385
|
+
}
|
|
386
|
+
async function DeleteWithProgress(RootPath, Options = {}) {
|
|
387
|
+
const Progress = {
|
|
388
|
+
Phase: "Scanning",
|
|
389
|
+
CurrentPath: null,
|
|
390
|
+
DiscoveredEntries: 0,
|
|
391
|
+
TotalEntries: 0,
|
|
392
|
+
DeletedEntries: 0,
|
|
393
|
+
TotalBytes: 0,
|
|
394
|
+
DeletedBytes: 0
|
|
395
|
+
};
|
|
396
|
+
const Entries = await BuildDeletionPlan(RootPath, Progress, Options);
|
|
397
|
+
Progress.Phase = "Deleting";
|
|
398
|
+
Progress.TotalEntries = Entries.length;
|
|
399
|
+
Progress.CurrentPath = null;
|
|
400
|
+
Options.OnProgress?.(CloneProgress(Progress));
|
|
401
|
+
for (const Entry of Entries) {
|
|
402
|
+
Options.Signal?.throwIfAborted();
|
|
403
|
+
Progress.CurrentPath = Entry.EntryPath;
|
|
404
|
+
Options.OnProgress?.(CloneProgress(Progress));
|
|
405
|
+
try {
|
|
406
|
+
if (Entry.Kind === "Directory") {
|
|
407
|
+
await FileSystem.rmdir(Entry.EntryPath);
|
|
408
|
+
} else {
|
|
409
|
+
await FileSystem.unlink(Entry.EntryPath);
|
|
410
|
+
}
|
|
411
|
+
} catch (ErrorValue) {
|
|
412
|
+
if (!IsMissingFileError(ErrorValue)) {
|
|
413
|
+
throw ErrorValue;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
Progress.DeletedEntries += 1;
|
|
417
|
+
Progress.DeletedBytes += Entry.Size;
|
|
418
|
+
Options.OnProgress?.(CloneProgress(Progress));
|
|
419
|
+
}
|
|
420
|
+
Progress.Phase = "Done";
|
|
421
|
+
Progress.CurrentPath = null;
|
|
422
|
+
Options.OnProgress?.(CloneProgress(Progress));
|
|
332
423
|
}
|
|
333
424
|
|
|
334
425
|
// Source/Functional/index.ts
|
|
@@ -338,8 +429,8 @@ __export(Functional_exports, {
|
|
|
338
429
|
});
|
|
339
430
|
|
|
340
431
|
// Source/Functional/Functional.ts
|
|
341
|
-
function Identity(...
|
|
342
|
-
return
|
|
432
|
+
function Identity(...ArgumentVector) {
|
|
433
|
+
return ArgumentVector;
|
|
343
434
|
}
|
|
344
435
|
|
|
345
436
|
// Source/Math/index.ts
|
|
@@ -487,8 +578,8 @@ var RootDirectoryNotFoundError = class extends import_effect.Data.TaggedError("R
|
|
|
487
578
|
// Source/Npm/Npm.ts
|
|
488
579
|
var import_path2 = require("path");
|
|
489
580
|
var import_process = __toESM(require("process"), 1);
|
|
490
|
-
async function GetPackageJson(
|
|
491
|
-
const RootDirectory = await GetPackageRootDirectory(
|
|
581
|
+
async function GetPackageJson(Path2) {
|
|
582
|
+
const RootDirectory = await GetPackageRootDirectory(Path2);
|
|
492
583
|
const PackageJsonPath = (0, import_path2.join)(RootDirectory, "package.json");
|
|
493
584
|
const FileContents = await import_fs3.promises.readFile(PackageJsonPath, "utf-8");
|
|
494
585
|
const PackageJson = await (async () => {
|
|
@@ -500,8 +591,8 @@ async function GetPackageJson(Path) {
|
|
|
500
591
|
})();
|
|
501
592
|
return PackageJson;
|
|
502
593
|
}
|
|
503
|
-
async function GetPackageRootDirectory(
|
|
504
|
-
let CurrentDirectory = await import_fs3.promises.realpath(
|
|
594
|
+
async function GetPackageRootDirectory(Path2) {
|
|
595
|
+
let CurrentDirectory = await import_fs3.promises.realpath(Path2 ?? import_process.default.cwd());
|
|
505
596
|
while (true) {
|
|
506
597
|
const PackageJsonPath = (0, import_path2.join)(CurrentDirectory, "package.json");
|
|
507
598
|
const PackageJsonExists = await (async () => {
|
|
@@ -517,7 +608,7 @@ async function GetPackageRootDirectory(Path) {
|
|
|
517
608
|
}
|
|
518
609
|
const ParentDirectory = (0, import_path2.dirname)(CurrentDirectory);
|
|
519
610
|
if (ParentDirectory === CurrentDirectory) {
|
|
520
|
-
throw new RootDirectoryNotFoundError({ Path });
|
|
611
|
+
throw new RootDirectoryNotFoundError({ Path: Path2 });
|
|
521
612
|
}
|
|
522
613
|
CurrentDirectory = ParentDirectory;
|
|
523
614
|
}
|
|
@@ -557,21 +648,43 @@ var FPath = class _FPath {
|
|
|
557
648
|
// Source/String/index.ts
|
|
558
649
|
var String_exports = {};
|
|
559
650
|
__export(String_exports, {
|
|
651
|
+
Dedent: () => Dedent,
|
|
560
652
|
IsAlpha: () => IsAlpha,
|
|
561
653
|
IsLetters: () => IsLetters,
|
|
562
654
|
IsNumeric: () => IsNumeric
|
|
563
655
|
});
|
|
564
656
|
|
|
565
657
|
// Source/String/String.ts
|
|
566
|
-
function IsLetters(
|
|
567
|
-
return /^[a-zA-Z]*$/.test(
|
|
658
|
+
function IsLetters(TestString) {
|
|
659
|
+
return /^[a-zA-Z]*$/.test(TestString);
|
|
660
|
+
}
|
|
661
|
+
function IsAlpha(TestString) {
|
|
662
|
+
return IsLetters(TestString);
|
|
568
663
|
}
|
|
569
|
-
function
|
|
570
|
-
return
|
|
664
|
+
function IsNumeric(TestString) {
|
|
665
|
+
return /^\d+$/.test(TestString);
|
|
571
666
|
}
|
|
572
|
-
function
|
|
573
|
-
|
|
667
|
+
function Dedent(Content, IndentLength) {
|
|
668
|
+
const WhitespaceSubstring = (() => {
|
|
669
|
+
if (IndentLength !== void 0) {
|
|
670
|
+
return "\n" + " ".repeat(IndentLength);
|
|
671
|
+
}
|
|
672
|
+
let WhitespaceSubstring2 = "\n";
|
|
673
|
+
while (true) {
|
|
674
|
+
const TestString = WhitespaceSubstring2 + " ";
|
|
675
|
+
if (Content.includes(TestString)) {
|
|
676
|
+
WhitespaceSubstring2 = TestString;
|
|
677
|
+
} else {
|
|
678
|
+
break;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return WhitespaceSubstring2;
|
|
682
|
+
})();
|
|
683
|
+
return Content.replaceAll(WhitespaceSubstring, "");
|
|
574
684
|
}
|
|
685
|
+
|
|
686
|
+
// Source/TsConfig/index.ts
|
|
687
|
+
var TsConfig_exports = {};
|
|
575
688
|
/**
|
|
576
689
|
* @file Array.ts
|
|
577
690
|
* @author Gage Sorrell <gage@sorrell.sh>
|
|
@@ -698,4 +811,10 @@ function IsNumeric(In) {
|
|
|
698
811
|
* @copyright (c) 2026 Gage Sorrell
|
|
699
812
|
* @license MIT
|
|
700
813
|
*/
|
|
814
|
+
/**
|
|
815
|
+
* @file TsConfig.Types.ts
|
|
816
|
+
* @author Gage Sorrell <gage@sorrell.sh>
|
|
817
|
+
* @copyright (c) 2026 Gage Sorrell
|
|
818
|
+
* @license MIT
|
|
819
|
+
*/
|
|
701
820
|
//# sourceMappingURL=index.cjs.map
|