@sorrell/utilities 1.1.59 → 1.1.61

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.
Files changed (44) hide show
  1. package/Distribution/CJS/fs.js +9 -5
  2. package/Distribution/CJS/fs.js.map +3 -3
  3. package/Distribution/CJS/functional.js.map +2 -2
  4. package/Distribution/CJS/index.js +41 -53
  5. package/Distribution/CJS/index.js.map +3 -3
  6. package/Distribution/CJS/npm-effect.js +130 -0
  7. package/Distribution/CJS/npm-effect.js.map +7 -0
  8. package/Distribution/CJS/npm.js +31 -47
  9. package/Distribution/CJS/npm.js.map +3 -3
  10. package/Distribution/ESM/fs.js +9 -5
  11. package/Distribution/ESM/fs.js.map +2 -2
  12. package/Distribution/ESM/functional.js.map +2 -2
  13. package/Distribution/ESM/index.js +41 -53
  14. package/Distribution/ESM/index.js.map +3 -3
  15. package/Distribution/ESM/npm-effect.js +97 -0
  16. package/Distribution/ESM/npm-effect.js.map +7 -0
  17. package/Distribution/ESM/npm.js +31 -47
  18. package/Distribution/ESM/npm.js.map +2 -2
  19. package/Distribution/Types/FileSystem/FileSystem.d.ts +20 -0
  20. package/Distribution/Types/FileSystem/FileSystem.d.ts.map +1 -1
  21. package/Distribution/Types/Functional/Functional.Internal.Types.d.ts +9 -0
  22. package/Distribution/Types/Functional/Functional.Internal.Types.d.ts.map +1 -0
  23. package/Distribution/Types/Functional/Functional.Internal.d.ts +8 -0
  24. package/Distribution/Types/Functional/Functional.Internal.d.ts.map +1 -0
  25. package/Distribution/Types/Functional/Functional.d.ts.map +1 -1
  26. package/Distribution/Types/Npm/Index.Effect.d.ts +9 -0
  27. package/Distribution/Types/Npm/Index.Effect.d.ts.map +1 -0
  28. package/Distribution/Types/Npm/Npm.Effect.Internal.d.ts +17 -0
  29. package/Distribution/Types/Npm/Npm.Effect.Internal.d.ts.map +1 -0
  30. package/Distribution/Types/Npm/Npm.Effect.Types.d.ts +12 -0
  31. package/Distribution/Types/Npm/Npm.Effect.Types.d.ts.map +1 -0
  32. package/Distribution/Types/Npm/Npm.Effect.d.ts +92 -0
  33. package/Distribution/Types/Npm/Npm.Effect.d.ts.map +1 -0
  34. package/Distribution/Types/Npm/Npm.Error.d.ts +5 -3
  35. package/Distribution/Types/Npm/Npm.Error.d.ts.map +1 -1
  36. package/Distribution/Types/Npm/Npm.d.ts +26 -19
  37. package/Distribution/Types/Npm/Npm.d.ts.map +1 -1
  38. package/Distribution/Types/Npm/index.d.ts +0 -1
  39. package/Distribution/Types/Npm/index.d.ts.map +1 -1
  40. package/License.md +21 -0
  41. package/ReadMe.md +2 -2
  42. package/package.json +7 -5
  43. package/Distribution/Types/Npm/Npm.Types.d.ts +0 -11
  44. package/Distribution/Types/Npm/Npm.Types.d.ts.map +0 -1
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // Source/Npm/Index.Effect.ts
31
+ var Index_Effect_exports = {};
32
+ __export(Index_Effect_exports, {
33
+ GetPackageJson: () => GetPackageJson,
34
+ GetPackageRootDirectory: () => GetPackageRootDirectory
35
+ });
36
+ module.exports = __toCommonJS(Index_Effect_exports);
37
+
38
+ // Source/Npm/Npm.Effect.ts
39
+ var import_fs = require("fs");
40
+
41
+ // Source/Npm/Npm.Error.ts
42
+ var import_effect = require("effect");
43
+ var PackageJsonParseError = class extends import_effect.Data.TaggedError("PackageJsonParseError") {
44
+ };
45
+ var RootDirectoryNotFoundError = class extends import_effect.Data.TaggedError("RootDirectoryNotFound") {
46
+ };
47
+
48
+ // Source/Npm/Npm.Effect.ts
49
+ var import_path = require("path");
50
+ var import_effect2 = require("effect");
51
+
52
+ // Source/Npm/Npm.Effect.Internal.ts
53
+ function HasErrorCode(Value) {
54
+ return typeof Value === "object" && Value !== null && "code" in Value && typeof Value.code === "string";
55
+ }
56
+
57
+ // Source/Npm/Npm.Effect.ts
58
+ var import_process = __toESM(require("process"), 1);
59
+ function GetPackageJson(Path) {
60
+ return import_effect2.Effect.gen(function* () {
61
+ const RootDirectory = yield* GetPackageRootDirectory(Path);
62
+ const PackageJsonPath = (0, import_path.join)(RootDirectory, "package.json");
63
+ const FileContents = yield* import_effect2.Effect.tryPromise({
64
+ catch: (Cause) => Cause,
65
+ try: () => import_fs.promises.readFile(PackageJsonPath, "utf-8")
66
+ }).pipe(import_effect2.Effect.catchAll((Cause) => import_effect2.Effect.die(Cause)));
67
+ const PackageJson = yield* import_effect2.Effect.try({
68
+ catch: (Cause) => new PackageJsonParseError({
69
+ Cause,
70
+ Path: PackageJsonPath
71
+ }),
72
+ try: () => JSON.parse(FileContents)
73
+ });
74
+ return PackageJson;
75
+ });
76
+ }
77
+ function GetPackageRootDirectory(Path) {
78
+ return import_effect2.Effect.gen(function* () {
79
+ let CurrentDirectory = yield* import_effect2.Effect.tryPromise({
80
+ catch: (Cause) => Cause,
81
+ try: () => import_fs.promises.realpath(Path ?? import_process.default.cwd())
82
+ }).pipe(import_effect2.Effect.catchAll((Cause) => import_effect2.Effect.die(Cause)));
83
+ while (true) {
84
+ const PackageJsonPath = (0, import_path.join)(CurrentDirectory, "package.json");
85
+ const PackageJsonExists = yield* import_effect2.Effect.tryPromise({
86
+ catch: (Cause) => Cause,
87
+ try: () => import_fs.promises.access(PackageJsonPath, import_fs.constants.F_OK)
88
+ }).pipe(import_effect2.Effect.as(true), import_effect2.Effect.catchIf((Cause) => HasErrorCode(Cause) && Cause.code === "ENOENT", () => import_effect2.Effect.succeed(false)), import_effect2.Effect.catchAll((Cause) => import_effect2.Effect.die(Cause)));
89
+ if (PackageJsonExists) {
90
+ return CurrentDirectory;
91
+ }
92
+ const ParentDirectory = (0, import_path.dirname)(CurrentDirectory);
93
+ if (ParentDirectory === CurrentDirectory) {
94
+ return yield* import_effect2.Effect.fail(new RootDirectoryNotFoundError({ Path }));
95
+ }
96
+ CurrentDirectory = ParentDirectory;
97
+ }
98
+ });
99
+ }
100
+ /**
101
+ * @file Npm.Error.ts
102
+ * @author Gage Sorrell <gage@sorrell.sh>
103
+ * @copyright (c) 2026 Gage Sorrell
104
+ * @license MIT
105
+ */
106
+ /**
107
+ * @file Npm.Effect.Internal.ts
108
+ * @author Gage Sorrell <gage@sorrell.sh>
109
+ * @copyright (c) 2026 Gage Sorrell
110
+ * @license MIT
111
+ */
112
+ /**
113
+ * @file Npm.Effect.ts
114
+ * @author Gage Sorrell <gage@sorrell.sh>
115
+ * @copyright (c) 2026 Gage Sorrell
116
+ * @license MIT
117
+ */
118
+ /**
119
+ * @file Npm.Effect.Types.ts
120
+ * @author Gage Sorrell <gage@sorrell.sh>
121
+ * @copyright (c) 2026 Gage Sorrell
122
+ * @license MIT
123
+ */
124
+ /**
125
+ * @file Index.Effect.ts
126
+ * @author Gage Sorrell <gage@sorrell.sh>
127
+ * @copyright (c) 2026 Gage Sorrell
128
+ * @license MIT
129
+ */
130
+ //# sourceMappingURL=npm-effect.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../Source/Npm/Index.Effect.ts", "../../Source/Npm/Npm.Effect.ts", "../../Source/Npm/Npm.Error.ts", "../../Source/Npm/Npm.Effect.Internal.ts"],
4
+ "sourcesContent": ["/**\n * @file Index.Effect.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nexport * from \"./Npm.Effect.ts\";\nexport * from \"./Npm.Effect.Types.ts\";\n", "/**\n * @file Npm.Effect.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nimport type { EGetPackageJson, EGetPackageRootDirectory } from \"./Npm.Effect.Types.ts\";\nimport { promises as Fs, constants as FsConstants } from \"fs\";\nimport { PackageJsonParseError, RootDirectoryNotFoundError } from \"./Npm.Error.ts\";\nimport { dirname, join } from \"path\";\nimport { Effect } from \"effect\";\nimport { HasErrorCode } from \"./Npm.Effect.Internal.ts\";\nimport type { IPackageJson } from \"package-json-type\";\nimport Process from \"process\";\n/**\n * Get the `package.json` of the Node.js project in which the\n * given path, or the current working directory, resides.\n *\n * @param Path - The given path from which to look for a root directory.\n *\n * @returns {EGetPackageJson} An Effect that succeeds with the parsed `package.json`, or fails\n * with {@link RootDirectoryNotFoundError} or {@link PackageJsonParseError}.\n *\n * @example\n * Suppose `process.cwd() === \"./MyPackage\"`,\n * ```typescript\n * Effect.gen(function* ()\n * {\n * const PackageJson: IPackageJson = yield* GetPackageJson();\n * // `PackageJson` <- *The parsed `package.json` of `MyPackage`.*\n * }\n * ```\n */\nexport function GetPackageJson(Path?: string): EGetPackageJson {\n return Effect.gen(function* () {\n const RootDirectory: string = yield* GetPackageRootDirectory(Path);\n const PackageJsonPath: string = join(RootDirectory, \"package.json\");\n const FileContents: string = yield* Effect.tryPromise({\n catch: (Cause: unknown) => Cause,\n try: () => Fs.readFile(PackageJsonPath, \"utf-8\")\n }).pipe(Effect.catchAll((Cause: unknown) => Effect.die(Cause)));\n const PackageJson: IPackageJson = yield* Effect.try({\n catch: (Cause: unknown) => new PackageJsonParseError({\n Cause,\n Path: PackageJsonPath\n }),\n try: () => JSON.parse(FileContents) as IPackageJson\n });\n return PackageJson;\n });\n}\n/**\n * Get the root directory of the Node.js project in which the\n * current working directory resides.\n *\n * @param Path - *(Optional)* The given path from which to look for a root directory.\n *\n * @returns {EGetPackageRootDirectory} An Effect that succeeds with the package root\n * directory, or fails with {@link RootDirectoryNotFoundError}.\n *\n * @example\n * Suppose `process.cwd()` is any one of the following,\n * - `/home/alex/myPackage`,\n * - `/home/alex/myPackage/src/MyModule`,\n * - `/home/alex/myPackage/resource/Images`,\n *\n * then,\n *\n * ```typescript\n * import { Effect } from \"effect\";\n * const Root: string = await Effect.runPromise(GetPackageRootDirectory());\n * // `Root` <- `\"/home/alex/myPackage\"`\n * ```\n *\n * @example\n * Suppose `TestPath === \"/home/alex/Documents\"` is *not* a NodeJS package root\n * (of course, neither are `/home/alex` or `/home`). Then,\n *\n * ```typescript\n * import { Effect } from \"effect\";\n * const TestPath: string = \"/home/alex/Documents\";\n * let Root: string | undefined = undefined;\n * try\n * {\n * Root = await Effect.runPromise(\n * GetPackageRootDirectory(TestPath)\n * );\n * }\n * catch (Error: unknown)\n * {\n * // `Error instanceof RootDirectoryNotFound`\n * }\n *\n * // `Root` <- `undefined`\n * ```\n *\n * @example\n * Suppose `process.cwd() === /home/alex/Downloads`, which is *not* a NodeJS package\n * (of course, neither are `/home/alex` or `/home`). Then,\n *\n * ```typescript\n * import { Effect } from \"effect\";\n * let Root: string | undefined = undefined;\n * try\n * {\n * Root = await Effect.runPromise(GetPackageRootDirectory());\n * }\n * catch (Error: unknown)\n * {\n * // `Error instanceof RootDirectoryNotFound`\n * }\n * // `Root` <- `undefined`\n * ```\n */\nexport function GetPackageRootDirectory(Path?: string): EGetPackageRootDirectory {\n return Effect.gen(function* () {\n let CurrentDirectory: string = yield* Effect.tryPromise({\n catch: (Cause: unknown) => Cause,\n try: () => Fs.realpath(Path ?? Process.cwd())\n }).pipe(Effect.catchAll((Cause: unknown) => Effect.die(Cause)));\n while (true) {\n const PackageJsonPath: string = join(CurrentDirectory, \"package.json\");\n const PackageJsonExists: boolean = yield* Effect.tryPromise({\n catch: (Cause: unknown) => Cause,\n try: () => Fs.access(PackageJsonPath, FsConstants.F_OK)\n }).pipe(Effect.as(true), Effect.catchIf((Cause: unknown): Cause is {\n readonly code: string;\n } => HasErrorCode(Cause) && Cause.code === \"ENOENT\", () => Effect.succeed(false)), Effect.catchAll((Cause: unknown) => Effect.die(Cause)));\n if (PackageJsonExists) {\n return CurrentDirectory;\n }\n const ParentDirectory: string = dirname(CurrentDirectory);\n if (ParentDirectory === CurrentDirectory) {\n return yield* Effect.fail(new RootDirectoryNotFoundError({ Path }));\n }\n CurrentDirectory = ParentDirectory;\n }\n });\n}\n", "/**\n * @file Npm.Error.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nimport { Data } from \"effect\";\n/**\n * An error describing that {@link GetPackageJson} failed to parse the discovered `package.json` file.\n *\n * @property {string | undefined} Path - The `Path` argument passed to the effect returning this error,\n * if one was given.\n * @property {unknown} Cause - The cause of this error.\n */\nexport class PackageJsonParseError extends Data.TaggedError(\"PackageJsonParseError\")<{\n readonly Path: string | undefined;\n readonly Cause: unknown;\n}> {\n}\n/**\n * An error describing that {@link GetPackageRootDirectory} failed.\n *\n * @property {string | undefined} Path - The `Path` argument passed to the effect returning\n * this error, if one was given.\n */\nexport class RootDirectoryNotFoundError extends Data.TaggedError(\"RootDirectoryNotFound\")<{\n readonly Path: string | undefined;\n}> {\n}\n", "/**\n * @file Npm.Effect.Internal.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 * Returns whether a given {@link Value} contains a `readonly` `string` `\"code\"`.\n *\n * @param Value - The value to test.\n * @returns {Value is { readonly code: string }} Whether {@link Value} is a\n * `{ readonly code: string }`.\n */\nexport function HasErrorCode(Value: unknown): Value is {\n readonly code: string;\n} {\n return typeof Value === \"object\"\n && Value !== null\n && \"code\" in Value\n && typeof (Value as {\n readonly code: unknown;\n }).code === \"string\";\n}\n/* eslint-enable jsdoc/require-example */\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACOA,gBAAyD;;;ACDzD,oBAAqB;AAQd,IAAM,wBAAN,cAAoC,mBAAK,YAAY,uBAAuB,EAGhF;AACH;AAOO,IAAM,6BAAN,cAAyC,mBAAK,YAAY,uBAAuB,EAErF;AACH;;;ADnBA,kBAA8B;AAC9B,IAAAA,iBAAuB;;;AEIhB,SAAS,aAAa,OAE3B;AACE,SAAO,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,OAAQ,MAER,SAAS;AACpB;;;AFVA,qBAAoB;AAoBb,SAAS,eAAe,MAAgC;AAC3D,SAAO,sBAAO,IAAI,aAAa;AAC3B,UAAM,gBAAwB,OAAO,wBAAwB,IAAI;AACjE,UAAM,sBAA0B,kBAAK,eAAe,cAAc;AAClE,UAAM,eAAuB,OAAO,sBAAO,WAAW;AAAA,MAClD,OAAO,CAAC,UAAmB;AAAA,MAC3B,KAAK,MAAM,UAAAC,SAAG,SAAS,iBAAiB,OAAO;AAAA,IACnD,CAAC,EAAE,KAAK,sBAAO,SAAS,CAAC,UAAmB,sBAAO,IAAI,KAAK,CAAC,CAAC;AAC9D,UAAM,cAA4B,OAAO,sBAAO,IAAI;AAAA,MAChD,OAAO,CAAC,UAAmB,IAAI,sBAAsB;AAAA,QACjD;AAAA,QACA,MAAM;AAAA,MACV,CAAC;AAAA,MACD,KAAK,MAAM,KAAK,MAAM,YAAY;AAAA,IACtC,CAAC;AACD,WAAO;AAAA,EACX,CAAC;AACL;AAgEO,SAAS,wBAAwB,MAAyC;AAC7E,SAAO,sBAAO,IAAI,aAAa;AAC3B,QAAI,mBAA2B,OAAO,sBAAO,WAAW;AAAA,MACpD,OAAO,CAAC,UAAmB;AAAA,MAC3B,KAAK,MAAM,UAAAA,SAAG,SAAS,QAAQ,eAAAC,QAAQ,IAAI,CAAC;AAAA,IAChD,CAAC,EAAE,KAAK,sBAAO,SAAS,CAAC,UAAmB,sBAAO,IAAI,KAAK,CAAC,CAAC;AAC9D,WAAO,MAAM;AACT,YAAM,sBAA0B,kBAAK,kBAAkB,cAAc;AACrE,YAAM,oBAA6B,OAAO,sBAAO,WAAW;AAAA,QACxD,OAAO,CAAC,UAAmB;AAAA,QAC3B,KAAK,MAAM,UAAAD,SAAG,OAAO,iBAAiB,UAAAE,UAAY,IAAI;AAAA,MAC1D,CAAC,EAAE,KAAK,sBAAO,GAAG,IAAI,GAAG,sBAAO,QAAQ,CAAC,UAEpC,aAAa,KAAK,KAAK,MAAM,SAAS,UAAU,MAAM,sBAAO,QAAQ,KAAK,CAAC,GAAG,sBAAO,SAAS,CAAC,UAAmB,sBAAO,IAAI,KAAK,CAAC,CAAC;AACzI,UAAI,mBAAmB;AACnB,eAAO;AAAA,MACX;AACA,YAAM,sBAA0B,qBAAQ,gBAAgB;AACxD,UAAI,oBAAoB,kBAAkB;AACtC,eAAO,OAAO,sBAAO,KAAK,IAAI,2BAA2B,EAAE,KAAK,CAAC,CAAC;AAAA,MACtE;AACA,yBAAmB;AAAA,IACvB;AAAA,EACJ,CAAC;AACL;",
6
+ "names": ["import_effect", "Fs", "Process", "FsConstants"]
7
+ }
@@ -49,51 +49,41 @@ var RootDirectoryNotFoundError = class extends import_effect.Data.TaggedError("R
49
49
 
50
50
  // Source/Npm/Npm.ts
51
51
  var import_path = require("path");
52
- var import_effect2 = require("effect");
53
52
  var import_process = __toESM(require("process"), 1);
54
- function HasErrorCode(Value) {
55
- return typeof Value === "object" && Value !== null && "code" in Value && typeof Value.code === "string";
56
- }
57
- function GetPackageJson(Path) {
58
- return import_effect2.Effect.gen(function* () {
59
- const RootDirectory = yield* GetPackageRootDirectory(Path);
60
- const PackageJsonPath = (0, import_path.join)(RootDirectory, "package.json");
61
- const FileContents = yield* import_effect2.Effect.tryPromise({
62
- catch: (Cause) => Cause,
63
- try: () => import_fs.promises.readFile(PackageJsonPath, "utf-8")
64
- }).pipe(import_effect2.Effect.catchAll((Cause) => import_effect2.Effect.die(Cause)));
65
- const PackageJson = yield* import_effect2.Effect.try({
66
- catch: (Cause) => new PackageJsonParseError({
67
- Cause,
68
- Path: PackageJsonPath
69
- }),
70
- try: () => JSON.parse(FileContents)
71
- });
72
- return PackageJson;
73
- });
53
+ async function GetPackageJson(Path) {
54
+ const RootDirectory = await GetPackageRootDirectory(Path);
55
+ const PackageJsonPath = (0, import_path.join)(RootDirectory, "package.json");
56
+ const FileContents = await import_fs.promises.readFile(PackageJsonPath, "utf-8");
57
+ const PackageJson = await (async () => {
58
+ try {
59
+ return JSON.parse(FileContents);
60
+ } catch (Cause) {
61
+ throw new PackageJsonParseError({ Cause, Path: PackageJsonPath });
62
+ }
63
+ })();
64
+ return PackageJson;
74
65
  }
75
- function GetPackageRootDirectory(Path) {
76
- return import_effect2.Effect.gen(function* () {
77
- let CurrentDirectory = yield* import_effect2.Effect.tryPromise({
78
- catch: (Cause) => Cause,
79
- try: () => import_fs.promises.realpath(Path ?? import_process.default.cwd())
80
- }).pipe(import_effect2.Effect.catchAll((Cause) => import_effect2.Effect.die(Cause)));
81
- while (true) {
82
- const PackageJsonPath = (0, import_path.join)(CurrentDirectory, "package.json");
83
- const PackageJsonExists = yield* import_effect2.Effect.tryPromise({
84
- catch: (Cause) => Cause,
85
- try: () => import_fs.promises.access(PackageJsonPath, import_fs.constants.F_OK)
86
- }).pipe(import_effect2.Effect.as(true), import_effect2.Effect.catchIf((Cause) => HasErrorCode(Cause) && Cause.code === "ENOENT", () => import_effect2.Effect.succeed(false)), import_effect2.Effect.catchAll((Cause) => import_effect2.Effect.die(Cause)));
87
- if (PackageJsonExists) {
88
- return CurrentDirectory;
89
- }
90
- const ParentDirectory = (0, import_path.dirname)(CurrentDirectory);
91
- if (ParentDirectory === CurrentDirectory) {
92
- return yield* import_effect2.Effect.fail(new RootDirectoryNotFoundError({ Path }));
66
+ async function GetPackageRootDirectory(Path) {
67
+ let CurrentDirectory = await import_fs.promises.realpath(Path ?? import_process.default.cwd());
68
+ while (true) {
69
+ const PackageJsonPath = (0, import_path.join)(CurrentDirectory, "package.json");
70
+ const PackageJsonExists = await (async () => {
71
+ try {
72
+ await import_fs.promises.access(PackageJsonPath, import_fs.constants.F_OK);
73
+ return true;
74
+ } catch {
75
+ return false;
93
76
  }
94
- CurrentDirectory = ParentDirectory;
77
+ })();
78
+ if (PackageJsonExists) {
79
+ return CurrentDirectory;
95
80
  }
96
- });
81
+ const ParentDirectory = (0, import_path.dirname)(CurrentDirectory);
82
+ if (ParentDirectory === CurrentDirectory) {
83
+ throw new RootDirectoryNotFoundError({ Path });
84
+ }
85
+ CurrentDirectory = ParentDirectory;
86
+ }
97
87
  }
98
88
  /**
99
89
  * @file Npm.Error.ts
@@ -107,12 +97,6 @@ function GetPackageRootDirectory(Path) {
107
97
  * @copyright (c) 2026 Gage Sorrell
108
98
  * @license MIT
109
99
  */
110
- /**
111
- * @file Npm.Types.ts
112
- * @author Gage Sorrell <gage@sorrell.sh>
113
- * @copyright (c) 2026 Gage Sorrell
114
- * @license MIT
115
- */
116
100
  /**
117
101
  * @file index.ts
118
102
  * @author Gage Sorrell <gage@sorrell.sh>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../Source/Npm/index.ts", "../../Source/Npm/Npm.ts", "../../Source/Npm/Npm.Error.ts"],
4
- "sourcesContent": ["/**\n * @file index.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\n/**\n * @module Npm\n * Utilities for working with `npm` (NodeJS) packages.\n * Many of these likely work with packages of other NodeJS\n * package managers and adjacent runtimes (*e.g.*, `bun` or `deno`).\n */\nexport * from \"./Npm.ts\";\nexport * from \"./Npm.Error.ts\";\nexport * from \"./Npm.Types.ts\";\n", "/**\n * @file Npm.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nimport { promises as Fs, constants as FsConstants } from \"fs\";\nimport { PackageJsonParseError, RootDirectoryNotFoundError } from \"./Npm.Error.ts\";\nimport { dirname, join } from \"path\";\nimport { Effect } from \"effect\";\nimport type { GetPackageJsonEffect } from \"./Npm.Types.ts\";\nimport type { IPackageJson } from \"package-json-type\";\nimport Process from \"process\";\n/* eslint-disable-next-line jsdoc/require-jsdoc */\nfunction HasErrorCode(Value: unknown): Value is {\n readonly code: string;\n} {\n return typeof Value === \"object\"\n && Value !== null\n && \"code\" in Value\n && typeof (Value as {\n readonly code: unknown;\n }).code === \"string\";\n}\n/**\n * Get the `package.json` of the Node.js project in which the\n * given path, or the current working directory, resides.\n *\n * @param Path - *(Optional)* The given path from which to look for a root directory.\n *\n * @returns An Effect that succeeds with the parsed `package.json`, or fails\n * with {@link RootDirectoryNotFoundError} or {@link PackageJsonParseError}.\n */\nexport function GetPackageJson(Path?: string): GetPackageJsonEffect {\n return Effect.gen(function* () {\n const RootDirectory: string = yield* GetPackageRootDirectory(Path);\n const PackageJsonPath: string = join(RootDirectory, \"package.json\");\n const FileContents: string = yield* Effect.tryPromise({\n catch: (Cause: unknown) => Cause,\n try: () => Fs.readFile(PackageJsonPath, \"utf-8\")\n }).pipe(Effect.catchAll((Cause: unknown) => Effect.die(Cause)));\n const PackageJson: IPackageJson = yield* Effect.try({\n catch: (Cause: unknown) => new PackageJsonParseError({\n Cause,\n Path: PackageJsonPath\n }),\n try: () => JSON.parse(FileContents) as IPackageJson\n });\n return PackageJson;\n });\n}\n/**\n * Get the root directory of the Node.js project in which the\n * current working directory resides.\n *\n * @param Path - *(Optional)* The given path from which to look for a root directory.\n *\n * @returns An Effect that succeeds with the package root directory, or fails\n * with {@link RootDirectoryNotFoundError}.\n *\n * @example\n * Suppose `process.cwd()` is any one of the following,\n * - `/home/alex/myPackage`,\n * - `/home/alex/myPackage/src/MyModule`,\n * - `/home/alex/myPackage/resource/Images`,\n *\n * then,\n *\n * ```typescript\n * import { Effect } from \"effect\";\n * const Root: string = await Effect.runPromise(GetPackageRootDirectory());\n * // `Root` <- `\"/home/alex/myPackage\"`\n * ```\n *\n * @example\n * Suppose `TestPath === \"/home/alex/Documents\"` is *not* a NodeJS package root\n * (of course, neither are `/home/alex` or `/home`). Then,\n *\n * ```typescript\n * import { Effect } from \"effect\";\n * const TestPath: string = \"/home/alex/Documents\";\n * let Root: string | undefined = undefined;\n * try\n * {\n * Root = await Effect.runPromise(\n * GetPackageRootDirectory(TestPath)\n * );\n * }\n * catch (Error: unknown)\n * {\n * // `Error instanceof RootDirectoryNotFound`\n * }\n *\n * // `Root` <- `undefined`\n * ```\n *\n * @example\n * Suppose `process.cwd() === /home/alex/Downloads`, which is *not* a NodeJS package\n * (of course, neither are `/home/alex` or `/home`). Then,\n *\n * ```typescript\n * import { Effect } from \"effect\";\n * let Root: string | undefined = undefined;\n * try\n * {\n * Root = await Effect.runPromise(GetPackageRootDirectory());\n * }\n * catch (Error: unknown)\n * {\n * // `Error instanceof RootDirectoryNotFound`\n * }\n * // `Root` <- `undefined`\n * ```\n */\nexport function GetPackageRootDirectory(Path?: string): Effect.Effect<string, RootDirectoryNotFoundError, never> {\n return Effect.gen(function* () {\n let CurrentDirectory: string = yield* Effect.tryPromise({\n catch: (Cause: unknown) => Cause,\n try: () => Fs.realpath(Path ?? Process.cwd())\n }).pipe(Effect.catchAll((Cause: unknown) => Effect.die(Cause)));\n while (true) {\n const PackageJsonPath: string = join(CurrentDirectory, \"package.json\");\n const PackageJsonExists: boolean = yield* Effect.tryPromise({\n catch: (Cause: unknown) => Cause,\n try: () => Fs.access(PackageJsonPath, FsConstants.F_OK)\n }).pipe(Effect.as(true), Effect.catchIf((Cause: unknown): Cause is {\n readonly code: string;\n } => HasErrorCode(Cause) && Cause.code === \"ENOENT\", () => Effect.succeed(false)), Effect.catchAll((Cause: unknown) => Effect.die(Cause)));\n if (PackageJsonExists) {\n return CurrentDirectory;\n }\n const ParentDirectory: string = dirname(CurrentDirectory);\n if (ParentDirectory === CurrentDirectory) {\n return yield* Effect.fail(new RootDirectoryNotFoundError({ Path }));\n }\n CurrentDirectory = ParentDirectory;\n }\n });\n}\n// export async function GetPackageRootDirectory(Path?: string): Promise<string>\n// {\n// let CurrentDirectory: string = await realpath(Path || Process.cwd());\n// while (true)\n// {\n// const PackageJsonPath: string = join(CurrentDirectory, \"package.json\");\n// try\n// {\n// await access(PackageJsonPath, FsConstants.F_OK);\n// return CurrentDirectory;\n// }\n// catch { /* Empty */ }\n// const ParentDirectory: string = dirname(CurrentDirectory);\n// if (ParentDirectory === CurrentDirectory)\n// {\n// throw new Error(\n// `Could not find a Node.js project root above \"${ Path || Process.cwd() }\".`\n// );\n// }\n// CurrentDirectory = ParentDirectory;\n// }\n// }\n", "/**\n * @file Npm.Error.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nimport { Data } from \"effect\";\n/**\n * An error describing that {@link GetPackageJson} failed to parse the discovered `package.json` file.\n *\n * @field Path - The `Path` argument passed to the effect returning this error, if one was given.\n * @field Cause - The cause of this error.\n */\nexport class PackageJsonParseError extends Data.TaggedError(\"PackageJsonParseError\")<{\n readonly Path: string | undefined;\n readonly Cause: unknown;\n}> {\n}\n/**\n * An error describing that {@link GetPackageRootDirectory} failed.\n *\n * @field Path - The `Path` argument passed to the effect returning this error, if one was given.\n */\nexport class RootDirectoryNotFoundError extends Data.TaggedError(\"RootDirectoryNotFound\")<{\n readonly Path: string | undefined;\n}> {\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACMA,gBAAyD;;;ACAzD,oBAAqB;AAOd,IAAM,wBAAN,cAAoC,mBAAK,YAAY,uBAAuB,EAGhF;AACH;AAMO,IAAM,6BAAN,cAAyC,mBAAK,YAAY,uBAAuB,EAErF;AACH;;;ADlBA,kBAA8B;AAC9B,IAAAA,iBAAuB;AAGvB,qBAAoB;AAEpB,SAAS,aAAa,OAEpB;AACE,SAAO,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,OAAQ,MAER,SAAS;AACpB;AAUO,SAAS,eAAe,MAAqC;AAChE,SAAO,sBAAO,IAAI,aAAa;AAC3B,UAAM,gBAAwB,OAAO,wBAAwB,IAAI;AACjE,UAAM,sBAA0B,kBAAK,eAAe,cAAc;AAClE,UAAM,eAAuB,OAAO,sBAAO,WAAW;AAAA,MAClD,OAAO,CAAC,UAAmB;AAAA,MAC3B,KAAK,MAAM,UAAAC,SAAG,SAAS,iBAAiB,OAAO;AAAA,IACnD,CAAC,EAAE,KAAK,sBAAO,SAAS,CAAC,UAAmB,sBAAO,IAAI,KAAK,CAAC,CAAC;AAC9D,UAAM,cAA4B,OAAO,sBAAO,IAAI;AAAA,MAChD,OAAO,CAAC,UAAmB,IAAI,sBAAsB;AAAA,QACjD;AAAA,QACA,MAAM;AAAA,MACV,CAAC;AAAA,MACD,KAAK,MAAM,KAAK,MAAM,YAAY;AAAA,IACtC,CAAC;AACD,WAAO;AAAA,EACX,CAAC;AACL;AAgEO,SAAS,wBAAwB,MAAyE;AAC7G,SAAO,sBAAO,IAAI,aAAa;AAC3B,QAAI,mBAA2B,OAAO,sBAAO,WAAW;AAAA,MACpD,OAAO,CAAC,UAAmB;AAAA,MAC3B,KAAK,MAAM,UAAAA,SAAG,SAAS,QAAQ,eAAAC,QAAQ,IAAI,CAAC;AAAA,IAChD,CAAC,EAAE,KAAK,sBAAO,SAAS,CAAC,UAAmB,sBAAO,IAAI,KAAK,CAAC,CAAC;AAC9D,WAAO,MAAM;AACT,YAAM,sBAA0B,kBAAK,kBAAkB,cAAc;AACrE,YAAM,oBAA6B,OAAO,sBAAO,WAAW;AAAA,QACxD,OAAO,CAAC,UAAmB;AAAA,QAC3B,KAAK,MAAM,UAAAD,SAAG,OAAO,iBAAiB,UAAAE,UAAY,IAAI;AAAA,MAC1D,CAAC,EAAE,KAAK,sBAAO,GAAG,IAAI,GAAG,sBAAO,QAAQ,CAAC,UAEpC,aAAa,KAAK,KAAK,MAAM,SAAS,UAAU,MAAM,sBAAO,QAAQ,KAAK,CAAC,GAAG,sBAAO,SAAS,CAAC,UAAmB,sBAAO,IAAI,KAAK,CAAC,CAAC;AACzI,UAAI,mBAAmB;AACnB,eAAO;AAAA,MACX;AACA,YAAM,sBAA0B,qBAAQ,gBAAgB;AACxD,UAAI,oBAAoB,kBAAkB;AACtC,eAAO,OAAO,sBAAO,KAAK,IAAI,2BAA2B,EAAE,KAAK,CAAC,CAAC;AAAA,MACtE;AACA,yBAAmB;AAAA,IACvB;AAAA,EACJ,CAAC;AACL;",
6
- "names": ["import_effect", "Fs", "Process", "FsConstants"]
4
+ "sourcesContent": ["/**\n * @file index.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\n/**\n * @module Npm\n * Utilities for working with `npm` (NodeJS) packages.\n * Many of these likely work with packages of other NodeJS\n * package managers and adjacent runtimes (*e.g.*, `bun` or `deno`).\n */\nexport * from \"./Npm.ts\";\nexport * from \"./Npm.Error.ts\";\n", "/**\n * @file Npm.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nimport { promises as Fs, constants as FsConstants } from \"fs\";\nimport { PackageJsonParseError, RootDirectoryNotFoundError } from \"./Npm.Error.ts\";\nimport { dirname, join } from \"path\";\nimport type { IPackageJson } from \"package-json-type\";\nimport Process from \"process\";\n/**\n * Get the `package.json` of the Node.js project in which the\n * given path, or the current working directory, resides.\n *\n * @param Path - The given path from which to look for a root directory.\n *\n * @throws {RootDirectoryNotFoundError | PackageJsonParseError} An error\n * describing either failure to identify a root directory, or failing to\n * parse the discovered `package.json`.\n *\n * @returns {Promise<IPackageJson>} The {@link IPackageJson} of {@link Path}\n * if provided, otherwise of `process.cwd()`.\n *\n * @example\n * Suppose `process.cwd() === \"./MyPackage\"`,\n * ```typescript\n * const PackageJson: IPackageJson = await GetPackageJson();\n * // `PackageJson` <- *The parsed `package.json` of `MyPackage`.*\n * ```\n */\nexport async function GetPackageJson(Path?: string): Promise<IPackageJson> {\n const RootDirectory: string = await GetPackageRootDirectory(Path);\n const PackageJsonPath: string = join(RootDirectory, \"package.json\");\n const FileContents: string = await Fs.readFile(PackageJsonPath, \"utf-8\");\n const PackageJson: IPackageJson = await (async (): Promise<IPackageJson> => {\n try {\n return JSON.parse(FileContents) as IPackageJson;\n }\n catch (Cause: unknown) {\n throw new PackageJsonParseError({ Cause, Path: PackageJsonPath });\n }\n })();\n return PackageJson;\n}\n/**\n * Get the root directory of the Node.js project in which the\n * current working directory resides.\n *\n * @param Path - The given path from which to look for a root directory.\n *\n * @throws {RootDirectoryNotFoundError} An error iff the root directory\n * of a NodeJS package could not be found.\n *\n * @returns {Promise<string>} The path to the root directory of the package\n * containing {@link Path} if specified, otherwise containing `process.cwd()`.\n *\n * @example\n * Suppose `process.cwd()` is any one of the following,\n * - `/home/alex/myPackage`,\n * - `/home/alex/myPackage/src/MyModule`,\n * - `/home/alex/myPackage/resource/Images`,\n *\n * then,\n *\n * ```typescript\n * const Root: string = await GetPackageRootDirectory();\n * // `Root` <- `\"/home/alex/myPackage\"`\n * ```\n *\n * @example\n * Suppose `TestPath === \"/home/alex/Documents\"` is *not* a NodeJS package root\n * (of course, neither are `/home/alex` or `/home`). Then,\n *\n * ```typescript\n * const TestPath: string = \"/home/alex/Documents\";\n * let Root: string | undefined = undefined;\n * try\n * {\n * Root = await GetPackageRootDirectory(TestPath);\n * }\n * catch (Error: unknown)\n * {\n * // `Error instanceof RootDirectoryNotFound`\n * }\n *\n * // `Root` <- `undefined`\n * ```\n *\n * @example\n * Suppose `process.cwd() === /home/alex/Downloads`, which is *not* a NodeJS package\n * (of course, neither are `/home/alex` or `/home`). Then,\n *\n * ```typescript\n * let Root: string | undefined = undefined;\n * try\n * {\n * Root = await GetPackageRootDirectory();\n * }\n * catch (Error: unknown)\n * {\n * // `Error instanceof RootDirectoryNotFound`\n * }\n * // `Root` <- `undefined`\n * ```\n */\nexport async function GetPackageRootDirectory(Path?: string): Promise<string> {\n let CurrentDirectory: string = await Fs.realpath(Path ?? Process.cwd());\n while (true) {\n const PackageJsonPath: string = join(CurrentDirectory, \"package.json\");\n const PackageJsonExists: boolean = await (async (): Promise<boolean> => {\n try {\n await Fs.access(PackageJsonPath, FsConstants.F_OK);\n return true;\n }\n catch {\n return false;\n }\n })();\n if (PackageJsonExists) {\n return CurrentDirectory;\n }\n const ParentDirectory: string = dirname(CurrentDirectory);\n if (ParentDirectory === CurrentDirectory) {\n throw new RootDirectoryNotFoundError({ Path });\n }\n CurrentDirectory = ParentDirectory;\n }\n}\n", "/**\n * @file Npm.Error.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nimport { Data } from \"effect\";\n/**\n * An error describing that {@link GetPackageJson} failed to parse the discovered `package.json` file.\n *\n * @property {string | undefined} Path - The `Path` argument passed to the effect returning this error,\n * if one was given.\n * @property {unknown} Cause - The cause of this error.\n */\nexport class PackageJsonParseError extends Data.TaggedError(\"PackageJsonParseError\")<{\n readonly Path: string | undefined;\n readonly Cause: unknown;\n}> {\n}\n/**\n * An error describing that {@link GetPackageRootDirectory} failed.\n *\n * @property {string | undefined} Path - The `Path` argument passed to the effect returning\n * this error, if one was given.\n */\nexport class RootDirectoryNotFoundError extends Data.TaggedError(\"RootDirectoryNotFound\")<{\n readonly Path: string | undefined;\n}> {\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACMA,gBAAyD;;;ACAzD,oBAAqB;AAQd,IAAM,wBAAN,cAAoC,mBAAK,YAAY,uBAAuB,EAGhF;AACH;AAOO,IAAM,6BAAN,cAAyC,mBAAK,YAAY,uBAAuB,EAErF;AACH;;;ADpBA,kBAA8B;AAE9B,qBAAoB;AAqBpB,eAAsB,eAAe,MAAsC;AACvE,QAAM,gBAAwB,MAAM,wBAAwB,IAAI;AAChE,QAAM,sBAA0B,kBAAK,eAAe,cAAc;AAClE,QAAM,eAAuB,MAAM,UAAAA,SAAG,SAAS,iBAAiB,OAAO;AACvE,QAAM,cAA4B,OAAO,YAAmC;AACxE,QAAI;AACA,aAAO,KAAK,MAAM,YAAY;AAAA,IAClC,SACO,OAAgB;AACnB,YAAM,IAAI,sBAAsB,EAAE,OAAO,MAAM,gBAAgB,CAAC;AAAA,IACpE;AAAA,EACJ,GAAG;AACH,SAAO;AACX;AA8DA,eAAsB,wBAAwB,MAAgC;AAC1E,MAAI,mBAA2B,MAAM,UAAAA,SAAG,SAAS,QAAQ,eAAAC,QAAQ,IAAI,CAAC;AACtE,SAAO,MAAM;AACT,UAAM,sBAA0B,kBAAK,kBAAkB,cAAc;AACrE,UAAM,oBAA6B,OAAO,YAA8B;AACpE,UAAI;AACA,cAAM,UAAAD,SAAG,OAAO,iBAAiB,UAAAE,UAAY,IAAI;AACjD,eAAO;AAAA,MACX,QACM;AACF,eAAO;AAAA,MACX;AAAA,IACJ,GAAG;AACH,QAAI,mBAAmB;AACnB,aAAO;AAAA,IACX;AACA,UAAM,sBAA0B,qBAAQ,gBAAgB;AACxD,QAAI,oBAAoB,kBAAkB;AACtC,YAAM,IAAI,2BAA2B,EAAE,KAAK,CAAC;AAAA,IACjD;AACA,uBAAmB;AAAA,EACvB;AACJ;",
6
+ "names": ["Fs", "Process", "FsConstants"]
7
7
  }
@@ -1,11 +1,11 @@
1
1
  // Source/FileSystem/FileSystem.ts
2
- import { access, open, unlink } from "fs/promises";
3
2
  import { basename, dirname, extname, join } from "path";
3
+ import { promises as Fs } from "fs";
4
4
  import { constants as FsConstants } from "fs";
5
5
  import os from "os";
6
6
  async function PathExists(Path) {
7
7
  try {
8
- await access(Path, FsConstants.F_OK);
8
+ await Fs.access(Path, FsConstants.F_OK);
9
9
  return true;
10
10
  } catch {
11
11
  return false;
@@ -55,20 +55,24 @@ async function IsValidFileName(DirectoryPath, FileName, PersistNewFile = false,
55
55
  }
56
56
  const FilePath = join(DirectoryPath, FileName);
57
57
  try {
58
- const ThisFileHandle = await open(FilePath, "wx");
58
+ const ThisFileHandle = await Fs.open(FilePath, "wx");
59
59
  await ThisFileHandle.close();
60
60
  if (!PersistNewFile) {
61
- await unlink(FilePath);
61
+ await Fs.unlink(FilePath);
62
62
  }
63
63
  return true;
64
64
  } catch {
65
65
  return false;
66
66
  }
67
67
  }
68
+ async function WriteTextFile(Path, Contents) {
69
+ await Fs.writeFile(Path, Contents, { encoding: "utf-8" });
70
+ }
68
71
  export {
69
72
  GetSafeNewPath,
70
73
  IsSupportedFileExtension,
71
- IsValidFileName
74
+ IsValidFileName,
75
+ WriteTextFile
72
76
  };
73
77
  /**
74
78
  * @file FileSystem.ts
@@ -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 { type FileHandle, access, open, unlink } from \"fs/promises\";\nimport { basename, dirname, extname, join } from \"path\";\nimport { type FFileExtension } from \"./FileSystem.Types.ts\";\nimport { constants as FsConstants } from \"fs\";\nimport os from \"os\";\nasync function PathExists(Path: string): Promise<boolean> {\n try {\n await 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 open(FilePath, \"wx\");\n await ThisFileHandle.close();\n if (!PersistNewFile) {\n await unlink(FilePath);\n }\n return true;\n }\n catch {\n return false;\n }\n}\n"],
5
- "mappings": ";AAMA,SAA0B,QAAQ,MAAM,cAAc;AACtD,SAAS,UAAU,SAAS,SAAS,YAAY;AAEjD,SAAS,aAAa,mBAAmB;AACzC,OAAO,QAAQ;AACf,eAAe,WAAW,MAAgC;AACtD,MAAI;AACA,UAAM,OAAO,MAAM,YAAY,IAAI;AACnC,WAAO;AAAA,EACX,QACM;AACF,WAAO;AAAA,EACX;AACJ;AAKO,SAAS,yBAAyB,WAAoC;AACzE,MAAI,sBAA8B,UAAU,MAAM,CAAC;AACnD,MAAI,oBAAoB,WAAW,GAAG,GAAG;AACrC,0BAAsB,oBAAoB,MAAM,CAAC;AAAA,EACrD;AACA,MAAI,oBAAoB,WAAW,GAAG;AAClC,WAAO;AAAA,EACX;AACA,MAAI,oBAAoB,SAAS,GAAG,KAC7B,oBAAoB,SAAS,IAAI,KACjC,oBAAoB,SAAS,IAAI,GAAG;AACvC,WAAO;AAAA,EACX;AACA,MAAI,GAAG,SAAS,MAAM,SAAS;AAE3B,UAAM,uBAAgC,yBAAyB,KAAK,mBAAmB;AACvF,QAAI,sBAAsB;AACtB,aAAO;AAAA,IACX;AACA,QAAI,SAAS,KAAK,mBAAmB,GAAG;AACpC,aAAO;AAAA,IACX;AAAA,EACJ;AACA,SAAO;AACX;AAOA,eAAsB,eAAe,QAAiC;AAClE,QAAM,gBAAwB,QAAQ,MAAM;AAC5C,QAAM,YAAoB,QAAQ,MAAM;AACxC,QAAM,WAAmB,SAAS,MAAM;AACxC,QAAM,eAAuB,cAAc,KACrC,WACA,SAAS,QAAQ,SAAS;AAChC,MAAI,gBAAwB;AAC5B,MAAI,QAAgB;AACpB,SAAO,MAAM,WAAW,aAAa,GAAG;AACpC,UAAM,oBAA4B,GAAG,YAAY,KAAK,KAAK,IAAI,SAAS;AACxE,oBAAgB,KAAK,eAAe,iBAAiB;AACrD;AAAA,EACJ;AACA,SAAO;AACX;AAeA,eAAsB,gBAAgB,eAAuB,UAAkB,iBAA0B,OAAO,YAAwC,QAA6B;AACjL,QAAM,gBAA4C,cAAc,SACzD,UAAU,WAAW,GAAG,KAAK,yBAAyB,SAAS,IAC5D,YACA,OACJ;AACN,QAAM,sBAAgC,kBAAkB,QACpD,kBAAkB,OAClB,CAAC,SAAS,SAAS,aAAa;AACpC,MAAI,qBAAqB;AACrB,WAAO;AAAA,EACX;AACA,QAAM,WAAmB,KAAK,eAAe,QAAQ;AACrD,MAAI;AACA,UAAM,iBAA6B,MAAM,KAAK,UAAU,IAAI;AAC5D,UAAM,eAAe,MAAM;AAC3B,QAAI,CAAC,gBAAgB;AACjB,YAAM,OAAO,QAAQ;AAAA,IACzB;AACA,WAAO;AAAA,EACX,QACM;AACF,WAAO;AAAA,EACX;AACJ;",
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;AACf,eAAe,WAAW,MAAgC;AACtD,MAAI;AACA,UAAM,GAAG,OAAO,MAAM,YAAY,IAAI;AACtC,WAAO;AAAA,EACX,QACM;AACF,WAAO;AAAA,EACX;AACJ;AAKO,SAAS,yBAAyB,WAAoC;AACzE,MAAI,sBAA8B,UAAU,MAAM,CAAC;AACnD,MAAI,oBAAoB,WAAW,GAAG,GAAG;AACrC,0BAAsB,oBAAoB,MAAM,CAAC;AAAA,EACrD;AACA,MAAI,oBAAoB,WAAW,GAAG;AAClC,WAAO;AAAA,EACX;AACA,MAAI,oBAAoB,SAAS,GAAG,KAC7B,oBAAoB,SAAS,IAAI,KACjC,oBAAoB,SAAS,IAAI,GAAG;AACvC,WAAO;AAAA,EACX;AACA,MAAI,GAAG,SAAS,MAAM,SAAS;AAE3B,UAAM,uBAAgC,yBAAyB,KAAK,mBAAmB;AACvF,QAAI,sBAAsB;AACtB,aAAO;AAAA,IACX;AACA,QAAI,SAAS,KAAK,mBAAmB,GAAG;AACpC,aAAO;AAAA,IACX;AAAA,EACJ;AACA,SAAO;AACX;AAOA,eAAsB,eAAe,QAAiC;AAClE,QAAM,gBAAwB,QAAQ,MAAM;AAC5C,QAAM,YAAoB,QAAQ,MAAM;AACxC,QAAM,WAAmB,SAAS,MAAM;AACxC,QAAM,eAAuB,cAAc,KACrC,WACA,SAAS,QAAQ,SAAS;AAChC,MAAI,gBAAwB;AAC5B,MAAI,QAAgB;AACpB,SAAO,MAAM,WAAW,aAAa,GAAG;AACpC,UAAM,oBAA4B,GAAG,YAAY,KAAK,KAAK,IAAI,SAAS;AACxE,oBAAgB,KAAK,eAAe,iBAAiB;AACrD;AAAA,EACJ;AACA,SAAO;AACX;AAeA,eAAsB,gBAAgB,eAAuB,UAAkB,iBAA0B,OAAO,YAAwC,QAA6B;AACjL,QAAM,gBAA4C,cAAc,SACzD,UAAU,WAAW,GAAG,KAAK,yBAAyB,SAAS,IAC5D,YACA,OACJ;AACN,QAAM,sBAAgC,kBAAkB,QACpD,kBAAkB,OAClB,CAAC,SAAS,SAAS,aAAa;AACpC,MAAI,qBAAqB;AACrB,WAAO;AAAA,EACX;AACA,QAAM,WAAmB,KAAK,eAAe,QAAQ;AACrD,MAAI;AACA,UAAM,iBAA6B,MAAM,GAAG,KAAK,UAAU,IAAI;AAC/D,UAAM,eAAe,MAAM;AAC3B,QAAI,CAAC,gBAAgB;AACjB,YAAM,GAAG,OAAO,QAAQ;AAAA,IAC5B;AACA,WAAO;AAAA,EACX,QACM;AACF,WAAO;AAAA,EACX;AACJ;AAoBA,eAAsB,cAAc,MAAc,UAAiC;AAC/E,QAAM,GAAG,UAAU,MAAM,UAAU,EAAE,UAAU,QAAQ,CAAC;AAC5D;",
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 */\nexport function Identity<Type>(...Arguments: Array<Type>) {\n return Arguments;\n}\n"],
5
- "mappings": ";AAMO,SAAS,YAAkB,WAAwB;AACtD,SAAO;AACX;",
4
+ "sourcesContent": ["/**\n * @file Functional.ts\n * @author Gage Sorrell <gage@sorrell.sh>\n * @copyright (c) 2026 Gage Sorrell\n * @license MIT\n */\nimport { CurriedArgument } from \"./Functional.Internal\";\nimport type { FCurriedArgument } from \"./Functional.Internal.Types\";\nimport type { TFunction } from \"./Functional.Types\";\nexport function Identity<Type>(...Arguments: Array<Type>) {\n return Arguments;\n}\n"],
5
+ "mappings": ";AASO,SAAS,YAAkB,WAAwB;AACtD,SAAO;AACX;",
6
6
  "names": []
7
7
  }
@@ -217,17 +217,18 @@ var FileSystem_exports = {};
217
217
  __export(FileSystem_exports, {
218
218
  GetSafeNewPath: () => GetSafeNewPath,
219
219
  IsSupportedFileExtension: () => IsSupportedFileExtension,
220
- IsValidFileName: () => IsValidFileName
220
+ IsValidFileName: () => IsValidFileName,
221
+ WriteTextFile: () => WriteTextFile
221
222
  });
222
223
 
223
224
  // Source/FileSystem/FileSystem.ts
224
- import { access, open, unlink } from "fs/promises";
225
225
  import { basename, dirname, extname, join } from "path";
226
+ import { promises as Fs } from "fs";
226
227
  import { constants as FsConstants } from "fs";
227
228
  import os from "os";
228
229
  async function PathExists(Path) {
229
230
  try {
230
- await access(Path, FsConstants.F_OK);
231
+ await Fs.access(Path, FsConstants.F_OK);
231
232
  return true;
232
233
  } catch {
233
234
  return false;
@@ -277,16 +278,19 @@ async function IsValidFileName(DirectoryPath, FileName, PersistNewFile = false,
277
278
  }
278
279
  const FilePath = join(DirectoryPath, FileName);
279
280
  try {
280
- const ThisFileHandle = await open(FilePath, "wx");
281
+ const ThisFileHandle = await Fs.open(FilePath, "wx");
281
282
  await ThisFileHandle.close();
282
283
  if (!PersistNewFile) {
283
- await unlink(FilePath);
284
+ await Fs.unlink(FilePath);
284
285
  }
285
286
  return true;
286
287
  } catch {
287
288
  return false;
288
289
  }
289
290
  }
291
+ async function WriteTextFile(Path, Contents) {
292
+ await Fs.writeFile(Path, Contents, { encoding: "utf-8" });
293
+ }
290
294
 
291
295
  // Source/Functional/index.ts
292
296
  var Functional_exports = {};
@@ -432,7 +436,7 @@ __export(Npm_exports, {
432
436
  });
433
437
 
434
438
  // Source/Npm/Npm.ts
435
- import { promises as Fs, constants as FsConstants2 } from "fs";
439
+ import { promises as Fs2, constants as FsConstants2 } from "fs";
436
440
 
437
441
  // Source/Npm/Npm.Error.ts
438
442
  import { Data } from "effect";
@@ -443,51 +447,41 @@ var RootDirectoryNotFoundError = class extends Data.TaggedError("RootDirectoryNo
443
447
 
444
448
  // Source/Npm/Npm.ts
445
449
  import { dirname as dirname2, join as join2 } from "path";
446
- import { Effect } from "effect";
447
450
  import Process from "process";
448
- function HasErrorCode(Value) {
449
- return typeof Value === "object" && Value !== null && "code" in Value && typeof Value.code === "string";
450
- }
451
- function GetPackageJson(Path) {
452
- return Effect.gen(function* () {
453
- const RootDirectory = yield* GetPackageRootDirectory(Path);
454
- const PackageJsonPath = join2(RootDirectory, "package.json");
455
- const FileContents = yield* Effect.tryPromise({
456
- catch: (Cause) => Cause,
457
- try: () => Fs.readFile(PackageJsonPath, "utf-8")
458
- }).pipe(Effect.catchAll((Cause) => Effect.die(Cause)));
459
- const PackageJson = yield* Effect.try({
460
- catch: (Cause) => new PackageJsonParseError({
461
- Cause,
462
- Path: PackageJsonPath
463
- }),
464
- try: () => JSON.parse(FileContents)
465
- });
466
- return PackageJson;
467
- });
451
+ async function GetPackageJson(Path) {
452
+ const RootDirectory = await GetPackageRootDirectory(Path);
453
+ const PackageJsonPath = join2(RootDirectory, "package.json");
454
+ const FileContents = await Fs2.readFile(PackageJsonPath, "utf-8");
455
+ const PackageJson = await (async () => {
456
+ try {
457
+ return JSON.parse(FileContents);
458
+ } catch (Cause) {
459
+ throw new PackageJsonParseError({ Cause, Path: PackageJsonPath });
460
+ }
461
+ })();
462
+ return PackageJson;
468
463
  }
469
- function GetPackageRootDirectory(Path) {
470
- return Effect.gen(function* () {
471
- let CurrentDirectory = yield* Effect.tryPromise({
472
- catch: (Cause) => Cause,
473
- try: () => Fs.realpath(Path ?? Process.cwd())
474
- }).pipe(Effect.catchAll((Cause) => Effect.die(Cause)));
475
- while (true) {
476
- const PackageJsonPath = join2(CurrentDirectory, "package.json");
477
- const PackageJsonExists = yield* Effect.tryPromise({
478
- catch: (Cause) => Cause,
479
- try: () => Fs.access(PackageJsonPath, FsConstants2.F_OK)
480
- }).pipe(Effect.as(true), Effect.catchIf((Cause) => HasErrorCode(Cause) && Cause.code === "ENOENT", () => Effect.succeed(false)), Effect.catchAll((Cause) => Effect.die(Cause)));
481
- if (PackageJsonExists) {
482
- return CurrentDirectory;
464
+ async function GetPackageRootDirectory(Path) {
465
+ let CurrentDirectory = await Fs2.realpath(Path ?? Process.cwd());
466
+ while (true) {
467
+ const PackageJsonPath = join2(CurrentDirectory, "package.json");
468
+ const PackageJsonExists = await (async () => {
469
+ try {
470
+ await Fs2.access(PackageJsonPath, FsConstants2.F_OK);
471
+ return true;
472
+ } catch {
473
+ return false;
483
474
  }
484
- const ParentDirectory = dirname2(CurrentDirectory);
485
- if (ParentDirectory === CurrentDirectory) {
486
- return yield* Effect.fail(new RootDirectoryNotFoundError({ Path }));
487
- }
488
- CurrentDirectory = ParentDirectory;
475
+ })();
476
+ if (PackageJsonExists) {
477
+ return CurrentDirectory;
489
478
  }
490
- });
479
+ const ParentDirectory = dirname2(CurrentDirectory);
480
+ if (ParentDirectory === CurrentDirectory) {
481
+ throw new RootDirectoryNotFoundError({ Path });
482
+ }
483
+ CurrentDirectory = ParentDirectory;
484
+ }
491
485
  }
492
486
 
493
487
  // Source/Path/index.ts
@@ -665,12 +659,6 @@ export {
665
659
  * @copyright (c) 2026 Gage Sorrell
666
660
  * @license MIT
667
661
  */
668
- /**
669
- * @file Npm.Types.ts
670
- * @author Gage Sorrell <gage@sorrell.sh>
671
- * @copyright (c) 2026 Gage Sorrell
672
- * @license MIT
673
- */
674
662
  /**
675
663
  * @file Path.ts
676
664
  * @author Gage Sorrell <gage@sorrell.sh>