@sorrell/utilities 1.2.15 → 1.2.16
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 +10 -0
- package/Distribution/Types/FileSystem/FileSystem.d.cts +2 -0
- package/Distribution/Types/FileSystem/FileSystem.d.cts.map +1 -1
- package/Distribution/Types/FileSystem/FileSystem.d.mts +2 -0
- package/Distribution/Types/FileSystem/FileSystem.d.mts.map +1 -1
- package/Distribution/Types/FileSystem/FileSystem.d.ts +2 -0
- package/Distribution/Types/FileSystem/FileSystem.d.ts.map +1 -1
- package/Distribution/Types/FileSystem/Module/Module.Internal.d.cts +7 -0
- package/Distribution/Types/FileSystem/Module/Module.Internal.d.cts.map +10 -0
- package/Distribution/Types/FileSystem/Module/Module.Internal.d.mts +7 -0
- package/Distribution/Types/FileSystem/Module/Module.Internal.d.mts.map +10 -0
- package/Distribution/Types/FileSystem/Module/Module.Internal.d.ts +7 -0
- package/Distribution/Types/FileSystem/Module/Module.Internal.d.ts.map +1 -0
- package/Distribution/Types/FileSystem/Module/Module.Types.d.cts +14 -0
- package/Distribution/Types/FileSystem/Module/Module.Types.d.cts.map +10 -0
- package/Distribution/Types/FileSystem/Module/Module.Types.d.mts +14 -0
- package/Distribution/Types/FileSystem/Module/Module.Types.d.mts.map +10 -0
- package/Distribution/Types/FileSystem/Module/Module.Types.d.ts +14 -0
- package/Distribution/Types/FileSystem/Module/Module.Types.d.ts.map +1 -0
- package/Distribution/Types/FileSystem/Module/Module.d.cts +15 -0
- package/Distribution/Types/FileSystem/Module/Module.d.cts.map +10 -0
- package/Distribution/Types/FileSystem/Module/Module.d.mts +15 -0
- package/Distribution/Types/FileSystem/Module/Module.d.mts.map +10 -0
- package/Distribution/Types/FileSystem/Module/Module.d.ts +15 -0
- package/Distribution/Types/FileSystem/Module/Module.d.ts.map +1 -0
- package/Distribution/Types/FileSystem/Module/index.d.cts +9 -0
- package/Distribution/Types/FileSystem/Module/index.d.cts.map +10 -0
- package/Distribution/Types/FileSystem/Module/index.d.mts +9 -0
- package/Distribution/Types/FileSystem/Module/index.d.mts.map +10 -0
- package/Distribution/Types/FileSystem/Module/index.d.ts +9 -0
- package/Distribution/Types/FileSystem/Module/index.d.ts.map +1 -0
- package/Distribution/Types/FileSystem/index.d.cts +1 -0
- package/Distribution/Types/FileSystem/index.d.cts.map +1 -1
- package/Distribution/Types/FileSystem/index.d.mts +1 -0
- package/Distribution/Types/FileSystem/index.d.mts.map +1 -1
- package/Distribution/Types/FileSystem/index.d.ts +1 -0
- package/Distribution/Types/FileSystem/index.d.ts.map +1 -1
- package/Distribution/Types/String/String.d.cts +1 -0
- package/Distribution/Types/String/String.d.cts.map +1 -1
- package/Distribution/Types/String/String.d.mts +1 -0
- package/Distribution/Types/String/String.d.mts.map +1 -1
- package/Distribution/Types/String/String.d.ts +1 -0
- package/Distribution/Types/String/String.d.ts.map +1 -1
- package/Distribution/fs-module.cjs +161 -0
- package/Distribution/fs-module.cjs.map +7 -0
- package/Distribution/fs-module.js +128 -0
- package/Distribution/fs-module.js.map +7 -0
- package/Distribution/fs.cjs +116 -2
- package/Distribution/fs.cjs.map +4 -4
- package/Distribution/fs.js +125 -5
- package/Distribution/fs.js.map +4 -4
- package/Distribution/index.cjs +144 -37
- package/Distribution/index.cjs.map +4 -4
- package/Distribution/index.js +147 -40
- package/Distribution/index.js.map +4 -4
- package/Distribution/string.cjs +4 -0
- package/Distribution/string.cjs.map +2 -2
- package/Distribution/string.js +4 -0
- package/Distribution/string.js.map +2 -2
- package/package.json +11 -1
package/Distribution/fs.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 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}\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": "
|
|
6
|
-
"names": ["Path"]
|
|
3
|
+
"sources": ["../Source/FileSystem/FileSystem.ts", "../Source/FileSystem/Module/index.ts", "../Source/String/String.ts", "../Source/FileSystem/Module/Module.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 * as FileSystem from \"node:fs/promises\";\nimport * as Path from \"node:path\";\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/* eslint-disable-next-line @typescript-eslint/typedef */\nexport const ReservedWindowsFileNames = [\n \"CON\",\n \"PRN\",\n \"AUX\",\n \"NUL\",\n \"COM1\",\n \"COM2\",\n \"COM3\",\n \"COM4\",\n \"COM5\",\n \"COM6\",\n \"COM7\",\n \"COM8\",\n \"COM9\",\n \"LPT1\",\n \"LPT2\",\n \"LPT3\",\n \"LPT4\",\n \"LPT5\",\n \"LPT6\",\n \"LPT7\",\n \"LPT8\",\n \"LPT9\",\n] as const;\nexport const InvalidCharacters: RegExp = /[<>:\"/\\\\|?*\\u0000-\\u001F]/u;\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}\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", "/**\n * @file index.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nexport * from \"./Module.ts\";\nexport * from \"./Module.Types.ts\";\n", "/**\n * @file String.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\n/**\n * @module String\n * Functions for manipulating strings.\n */\n// @TODO TEMPORARY.\n/* eslint-disable jsdoc/require-example */\n/**\n * Does the given {@link TestString} contain only letters?\n * This is equivalent to Python's\n * {@link https://docs.python.org/3/library/stdtypes.html#str.isalpha | isalpha} function.\n *\n * @remarks This is an alias for {@link IsAlpha}.\n *\n * @param TestString - The string that you wish to test.\n *\n * @returns {boolean} Whether the given string contains *only* (Latin alphabet) letters.\n */\nexport function IsLetters(TestString: string): boolean {\n return /^[a-zA-Z]*$/.test(TestString);\n}\n/**\n * Does the given {@link TestString} contain only letters?\n * This is equivalent to Python's\n * {@link https://docs.python.org/3/library/stdtypes.html#str.isalpha | isalpha} function.\n *\n * @param TestString - The string that you wish to test.\n *\n * @returns {boolean} Whether the given string contains *only* (Latin alphabet) letters.\n */\nexport function IsAlpha(TestString: string): boolean {\n return IsLetters(TestString);\n}\n/**\n * Does the given {@link TestString} contain only digits?\n *\n * This is equivalent to Python's\n * {@link https://docs.python.org/3/library/stdtypes.html#str.isnumeric | isnumeric} function.\n *\n * @param TestString - The string that you wish to test.\n *\n * @returns {boolean} Whether the given string contains *only* numeric digits.\n */\nexport function IsNumeric(TestString: string): boolean {\n return /^\\d+$/.test(TestString);\n}\n/**\n * This function provides a convenient way to define long strings across multiple lines.\n * The linebreaks and leading indentation are removed from the final string.\n * Please see the example below for how this is to be done.\n *\n * @param Content - The given string to dedent.\n * @param IndentLength - The number of spaces for which this function will check. This\n * is necessary only if the number of spaces used in the {@link Content} is not a multiple\n * of two.\n *\n * @returns {string} The given {@link Content}, but with the spaces at the beginning\n * of each line (excluding the first line if no spaces exist in the first line) removed.\n *\n * @example\n * ```typescript\n * import { Dedent } from \"@sorrell/utilities/string\";\n *\n * const MyLongString: string = Dedent(`Lorem ipsum dolor sit amet, consectetur adipiscing elit,\n * sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad\n * minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea\n * commodo consequat.`);\n *\n * // `MyLongString` <- `\"Lorem ipsum dolor sit amet, consectetur adipiscing elit, \\\n * sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad \\\n * minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea \\\n * commodo consequat.\"`\n * ```\n */\nexport function Dedent(Content: string, IndentLength?: number): string {\n const WhitespaceSubstring: string = ((): string => {\n if (IndentLength !== undefined) {\n return \"\\n\" + \" \".repeat(IndentLength);\n }\n let WhitespaceSubstring: string = \"\\n\";\n while (true) {\n const TestString: string = WhitespaceSubstring + \" \";\n if (Content.includes(TestString)) {\n WhitespaceSubstring = TestString;\n }\n else {\n break;\n }\n }\n return WhitespaceSubstring;\n })();\n return Content.replaceAll(WhitespaceSubstring, \"\");\n}\nexport function GetUtf8ByteLength(Text: string): number {\n return new TextEncoder().encode(Text).length;\n}\n", "/**\n * @file Module.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nimport { InvalidCharacters, ReservedWindowsFileNames } from \"../FileSystem.ts\";\nimport type { ExtensionPolicy } from \"./Module.Types.ts\";\nimport { GetUtf8ByteLength } from \"../../String/String.ts\";\n/* eslint-disable @typescript-eslint/typedef */\nexport namespace ValidExtensions {\n export /**\n * The valid file extensions for TypeScript *source* modules.\n */ const Source = [\n \".ts\",\n \".tsx\",\n \".mts\",\n \".cts\"\n ] as const;\n export /**\n * The valid file extensions for TypeScript *declaration* modules.\n */ const Declaration = [\n \".d.ts\",\n \".d.mts\",\n \".d.cts\"\n ] as const;\n export /**\n * The valid file extensions for *any* TypeScript module.\n */ const Any = [\n \".ts\",\n \".tsx\",\n \".mts\",\n \".cts\",\n \".d.ts\",\n \".d.mts\",\n \".d.cts\"\n ] as const;\n}\n/* eslint-enable @typescript-eslint/typedef */\nexport function HasTypeScriptExtension(FileName: string): boolean {\n return /\\.(ts|tsx|mts|cts|d\\.ts|d\\.mts|d\\.cts)$/iu.test(FileName);\n}\nexport function IsValidFileName(FileName: string, ExtensionPolicy: ExtensionPolicy = \"Disallow\"): boolean {\n if (FileName.length === 0) {\n return false;\n }\n if (FileName === \".\" || FileName === \"..\") {\n return false;\n }\n const DoesExtensionSatisfyPolicy: boolean = ((ExtensionPolicy === \"Disallow\" && !HasTypeScriptExtension(FileName)) ||\n (ExtensionPolicy === \"Require\" && HasTypeScriptExtension(FileName)) ||\n (Array.isArray(ExtensionPolicy) && ExtensionPolicy.some(FileName.endsWith)));\n if (!DoesExtensionSatisfyPolicy) {\n return false;\n }\n if (FileName.endsWith(\".\") || FileName.endsWith(\" \")) {\n return false;\n }\n if (GetUtf8ByteLength(FileName) > 255) {\n return false;\n }\n if (InvalidCharacters.test(FileName)) {\n return false;\n }\n const FileNameWithoutDots: string | undefined = FileName.split(\".\")[0]?.toUpperCase();\n const FileNameContainsWindowsReserved: boolean = (FileNameWithoutDots !== undefined &&\n (ReservedWindowsFileNames as ReadonlyArray<string>).includes(FileNameWithoutDots));\n if (FileNameContainsWindowsReserved) {\n return false;\n }\n return true;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["join", "Path", "IsValidFileName", "ValidExtensions", "IsValidFileName"]
|
|
7
7
|
}
|
package/Distribution/index.cjs
CHANGED
|
@@ -265,18 +265,21 @@ var FileSystem_exports = {};
|
|
|
265
265
|
__export(FileSystem_exports, {
|
|
266
266
|
DeleteWithProgress: () => DeleteWithProgress,
|
|
267
267
|
GetSafeNewPath: () => GetSafeNewPath,
|
|
268
|
+
InvalidCharacters: () => InvalidCharacters,
|
|
268
269
|
IsSupportedFileExtension: () => IsSupportedFileExtension,
|
|
269
270
|
IsValidFileName: () => IsValidFileName,
|
|
271
|
+
Module: () => Module_exports,
|
|
272
|
+
ReservedWindowsFileNames: () => ReservedWindowsFileNames,
|
|
270
273
|
WriteTextFile: () => WriteTextFile
|
|
271
274
|
});
|
|
272
275
|
|
|
273
276
|
// Source/FileSystem/FileSystem.ts
|
|
277
|
+
var FileSystem = __toESM(require("node:fs/promises"), 1);
|
|
278
|
+
var Path = __toESM(require("node:path"), 1);
|
|
274
279
|
var import_path = require("path");
|
|
275
280
|
var import_fs = require("fs");
|
|
276
281
|
var import_fs2 = require("fs");
|
|
277
282
|
var import_os = __toESM(require("os"), 1);
|
|
278
|
-
var FileSystem = __toESM(require("node:fs/promises"), 1);
|
|
279
|
-
var Path = __toESM(require("node:path"), 1);
|
|
280
283
|
async function PathExists(Path2) {
|
|
281
284
|
try {
|
|
282
285
|
await import_fs.promises.access(Path2, import_fs2.constants.F_OK);
|
|
@@ -321,6 +324,31 @@ async function GetSafeNewPath(InPath) {
|
|
|
321
324
|
}
|
|
322
325
|
return CandidatePath;
|
|
323
326
|
}
|
|
327
|
+
var ReservedWindowsFileNames = [
|
|
328
|
+
"CON",
|
|
329
|
+
"PRN",
|
|
330
|
+
"AUX",
|
|
331
|
+
"NUL",
|
|
332
|
+
"COM1",
|
|
333
|
+
"COM2",
|
|
334
|
+
"COM3",
|
|
335
|
+
"COM4",
|
|
336
|
+
"COM5",
|
|
337
|
+
"COM6",
|
|
338
|
+
"COM7",
|
|
339
|
+
"COM8",
|
|
340
|
+
"COM9",
|
|
341
|
+
"LPT1",
|
|
342
|
+
"LPT2",
|
|
343
|
+
"LPT3",
|
|
344
|
+
"LPT4",
|
|
345
|
+
"LPT5",
|
|
346
|
+
"LPT6",
|
|
347
|
+
"LPT7",
|
|
348
|
+
"LPT8",
|
|
349
|
+
"LPT9"
|
|
350
|
+
];
|
|
351
|
+
var InvalidCharacters = /[<>:"/\\|?*\u0000-\u001F]/u;
|
|
324
352
|
async function IsValidFileName(DirectoryPath, FileName, PersistNewFile = false, Extension = void 0) {
|
|
325
353
|
const ExtensionSafe = Extension !== void 0 ? Extension.startsWith(".") && IsSupportedFileExtension(Extension) ? Extension : null : "";
|
|
326
354
|
const IsExtensionImproper = ExtensionSafe === null || ExtensionSafe === "." || !FileName.endsWith(ExtensionSafe);
|
|
@@ -430,6 +458,101 @@ async function DeleteWithProgress(RootPath, Options = {}) {
|
|
|
430
458
|
Options.OnProgress?.(CloneProgress(Progress));
|
|
431
459
|
}
|
|
432
460
|
|
|
461
|
+
// Source/FileSystem/Module/index.ts
|
|
462
|
+
var Module_exports = {};
|
|
463
|
+
__export(Module_exports, {
|
|
464
|
+
HasTypeScriptExtension: () => HasTypeScriptExtension,
|
|
465
|
+
IsValidFileName: () => IsValidFileName2,
|
|
466
|
+
ValidExtensions: () => ValidExtensions
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
// Source/String/String.ts
|
|
470
|
+
function IsLetters(TestString) {
|
|
471
|
+
return /^[a-zA-Z]*$/.test(TestString);
|
|
472
|
+
}
|
|
473
|
+
function IsAlpha(TestString) {
|
|
474
|
+
return IsLetters(TestString);
|
|
475
|
+
}
|
|
476
|
+
function IsNumeric(TestString) {
|
|
477
|
+
return /^\d+$/.test(TestString);
|
|
478
|
+
}
|
|
479
|
+
function Dedent(Content, IndentLength) {
|
|
480
|
+
const WhitespaceSubstring = (() => {
|
|
481
|
+
if (IndentLength !== void 0) {
|
|
482
|
+
return "\n" + " ".repeat(IndentLength);
|
|
483
|
+
}
|
|
484
|
+
let WhitespaceSubstring2 = "\n";
|
|
485
|
+
while (true) {
|
|
486
|
+
const TestString = WhitespaceSubstring2 + " ";
|
|
487
|
+
if (Content.includes(TestString)) {
|
|
488
|
+
WhitespaceSubstring2 = TestString;
|
|
489
|
+
} else {
|
|
490
|
+
break;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
return WhitespaceSubstring2;
|
|
494
|
+
})();
|
|
495
|
+
return Content.replaceAll(WhitespaceSubstring, "");
|
|
496
|
+
}
|
|
497
|
+
function GetUtf8ByteLength(Text) {
|
|
498
|
+
return new TextEncoder().encode(Text).length;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Source/FileSystem/Module/Module.ts
|
|
502
|
+
var ValidExtensions;
|
|
503
|
+
((ValidExtensions2) => {
|
|
504
|
+
ValidExtensions2.Source = [
|
|
505
|
+
".ts",
|
|
506
|
+
".tsx",
|
|
507
|
+
".mts",
|
|
508
|
+
".cts"
|
|
509
|
+
];
|
|
510
|
+
ValidExtensions2.Declaration = [
|
|
511
|
+
".d.ts",
|
|
512
|
+
".d.mts",
|
|
513
|
+
".d.cts"
|
|
514
|
+
];
|
|
515
|
+
ValidExtensions2.Any = [
|
|
516
|
+
".ts",
|
|
517
|
+
".tsx",
|
|
518
|
+
".mts",
|
|
519
|
+
".cts",
|
|
520
|
+
".d.ts",
|
|
521
|
+
".d.mts",
|
|
522
|
+
".d.cts"
|
|
523
|
+
];
|
|
524
|
+
})(ValidExtensions || (ValidExtensions = {}));
|
|
525
|
+
function HasTypeScriptExtension(FileName) {
|
|
526
|
+
return /\.(ts|tsx|mts|cts|d\.ts|d\.mts|d\.cts)$/iu.test(FileName);
|
|
527
|
+
}
|
|
528
|
+
function IsValidFileName2(FileName, ExtensionPolicy = "Disallow") {
|
|
529
|
+
if (FileName.length === 0) {
|
|
530
|
+
return false;
|
|
531
|
+
}
|
|
532
|
+
if (FileName === "." || FileName === "..") {
|
|
533
|
+
return false;
|
|
534
|
+
}
|
|
535
|
+
const DoesExtensionSatisfyPolicy = ExtensionPolicy === "Disallow" && !HasTypeScriptExtension(FileName) || ExtensionPolicy === "Require" && HasTypeScriptExtension(FileName) || Array.isArray(ExtensionPolicy) && ExtensionPolicy.some(FileName.endsWith);
|
|
536
|
+
if (!DoesExtensionSatisfyPolicy) {
|
|
537
|
+
return false;
|
|
538
|
+
}
|
|
539
|
+
if (FileName.endsWith(".") || FileName.endsWith(" ")) {
|
|
540
|
+
return false;
|
|
541
|
+
}
|
|
542
|
+
if (GetUtf8ByteLength(FileName) > 255) {
|
|
543
|
+
return false;
|
|
544
|
+
}
|
|
545
|
+
if (InvalidCharacters.test(FileName)) {
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
548
|
+
const FileNameWithoutDots = FileName.split(".")[0]?.toUpperCase();
|
|
549
|
+
const FileNameContainsWindowsReserved = FileNameWithoutDots !== void 0 && ReservedWindowsFileNames.includes(FileNameWithoutDots);
|
|
550
|
+
if (FileNameContainsWindowsReserved) {
|
|
551
|
+
return false;
|
|
552
|
+
}
|
|
553
|
+
return true;
|
|
554
|
+
}
|
|
555
|
+
|
|
433
556
|
// Source/Functional/index.ts
|
|
434
557
|
var Functional_exports = {};
|
|
435
558
|
__export(Functional_exports, {
|
|
@@ -743,40 +866,12 @@ function FlatMap(InRecord, InFunction) {
|
|
|
743
866
|
var String_exports = {};
|
|
744
867
|
__export(String_exports, {
|
|
745
868
|
Dedent: () => Dedent,
|
|
869
|
+
GetUtf8ByteLength: () => GetUtf8ByteLength,
|
|
746
870
|
IsAlpha: () => IsAlpha,
|
|
747
871
|
IsLetters: () => IsLetters,
|
|
748
872
|
IsNumeric: () => IsNumeric
|
|
749
873
|
});
|
|
750
874
|
|
|
751
|
-
// Source/String/String.ts
|
|
752
|
-
function IsLetters(TestString) {
|
|
753
|
-
return /^[a-zA-Z]*$/.test(TestString);
|
|
754
|
-
}
|
|
755
|
-
function IsAlpha(TestString) {
|
|
756
|
-
return IsLetters(TestString);
|
|
757
|
-
}
|
|
758
|
-
function IsNumeric(TestString) {
|
|
759
|
-
return /^\d+$/.test(TestString);
|
|
760
|
-
}
|
|
761
|
-
function Dedent(Content, IndentLength) {
|
|
762
|
-
const WhitespaceSubstring = (() => {
|
|
763
|
-
if (IndentLength !== void 0) {
|
|
764
|
-
return "\n" + " ".repeat(IndentLength);
|
|
765
|
-
}
|
|
766
|
-
let WhitespaceSubstring2 = "\n";
|
|
767
|
-
while (true) {
|
|
768
|
-
const TestString = WhitespaceSubstring2 + " ";
|
|
769
|
-
if (Content.includes(TestString)) {
|
|
770
|
-
WhitespaceSubstring2 = TestString;
|
|
771
|
-
} else {
|
|
772
|
-
break;
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
return WhitespaceSubstring2;
|
|
776
|
-
})();
|
|
777
|
-
return Content.replaceAll(WhitespaceSubstring, "");
|
|
778
|
-
}
|
|
779
|
-
|
|
780
875
|
// Source/TsConfig/index.ts
|
|
781
876
|
var TsConfig_exports = {};
|
|
782
877
|
|
|
@@ -845,6 +940,24 @@ var Type_exports = {};
|
|
|
845
940
|
* @copyright (c) 2026 Gage Sorrell
|
|
846
941
|
* @license MIT
|
|
847
942
|
*/
|
|
943
|
+
/**
|
|
944
|
+
* @file String.ts
|
|
945
|
+
* @author Gage Sorrell <gage@sorrell.sh>
|
|
946
|
+
* @copyright (c) 2026 Gage Sorrell
|
|
947
|
+
* @license MIT
|
|
948
|
+
*/
|
|
949
|
+
/**
|
|
950
|
+
* @file Module.ts
|
|
951
|
+
* @author Gage Sorrell <gage@sorrell.sh>
|
|
952
|
+
* @copyright (c) 2026 Gage Sorrell
|
|
953
|
+
* @license MIT
|
|
954
|
+
*/
|
|
955
|
+
/**
|
|
956
|
+
* @file Module.Types.ts
|
|
957
|
+
* @author Gage Sorrell <gage@sorrell.sh>
|
|
958
|
+
* @copyright (c) 2026 Gage Sorrell
|
|
959
|
+
* @license MIT
|
|
960
|
+
*/
|
|
848
961
|
/**
|
|
849
962
|
* @file Functional.ts
|
|
850
963
|
* @author Gage Sorrell <gage@sorrell.sh>
|
|
@@ -917,12 +1030,6 @@ var Type_exports = {};
|
|
|
917
1030
|
* @copyright (c) 2026 Gage Sorrell
|
|
918
1031
|
* @license MIT
|
|
919
1032
|
*/
|
|
920
|
-
/**
|
|
921
|
-
* @file String.ts
|
|
922
|
-
* @author Gage Sorrell <gage@sorrell.sh>
|
|
923
|
-
* @copyright (c) 2026 Gage Sorrell
|
|
924
|
-
* @license MIT
|
|
925
|
-
*/
|
|
926
1033
|
/**
|
|
927
1034
|
* @file TsConfig.Types.ts
|
|
928
1035
|
* @author Gage Sorrell <gage@sorrell.sh>
|