functype-os 0.60.0 → 0.60.6

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Jordan Burke
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigResolver.js","names":["ConfigErrorConstructor"],"sources":["../../src/config/ConfigResolver.ts"],"sourcesContent":["import type { Either, TaskResult } from \"functype\"\nimport { Err, Left, List, Ok, Option, Right } from \"functype\"\n\nimport type { ConfigError } from \"../errors/errors\"\nimport { ConfigError as ConfigErrorConstructor } from \"../errors/errors\"\nimport { Fs } from \"../fs/Fs\"\nimport { expandPath } from \"../path/PathExpander\"\n\nconst tryExpandPath = (candidate: string): Option<string> => {\n const result = expandPath(candidate)\n return result.fold(\n () => Option<string>(undefined),\n (v) => Option(v),\n )\n}\n\nexport const ConfigResolver = {\n // Async methods — return TaskResult<T>\n\n resolve: async (options: { readonly candidates: readonly string[] }): TaskResult<Option<string>> => {\n for (const candidate of options.candidates) {\n const expanded = tryExpandPath(candidate)\n if (expanded.isNone()) continue\n\n const existsResult = await Fs.exists(expanded.orThrow())\n if (existsResult.isErr()) continue\n if (existsResult.value) {\n return Ok(expanded)\n }\n }\n return Ok(Option<string>(undefined))\n },\n\n resolveRequired: async (options: { readonly candidates: readonly string[] }): TaskResult<string> => {\n const result = await ConfigResolver.resolve(options)\n if (result.isErr()) return Err(result.error)\n\n const optValue = result.orThrow()\n if (optValue.isSome()) {\n return Ok(optValue.orThrow())\n }\n\n return Err(ConfigErrorConstructor(options.candidates))\n },\n\n resolveAll: async (options: { readonly candidates: readonly string[] }): TaskResult<List<string>> => {\n const found: readonly string[] = options.candidates.reduce<readonly string[]>((acc, candidate) => {\n const expanded = tryExpandPath(candidate)\n if (expanded.isNone()) return acc\n return [...acc, expanded.orThrow()]\n }, [])\n\n const results: string[] = []\n for (const expanded of found) {\n const existsResult = await Fs.exists(expanded)\n if (existsResult.isOk() && existsResult.value) {\n results.push(expanded)\n }\n }\n\n return Ok(List(results))\n },\n\n // Sync methods — return Either<ConfigError, T>\n\n resolveSync: (options: { readonly candidates: readonly string[] }): Option<string> => {\n for (const candidate of options.candidates) {\n const expanded = tryExpandPath(candidate)\n if (expanded.isNone()) continue\n if (Fs.existsSync(expanded.orThrow())) {\n return expanded\n }\n }\n return Option<string>(undefined)\n },\n\n resolveRequiredSync: (options: { readonly candidates: readonly string[] }): Either<ConfigError, string> => {\n const result = ConfigResolver.resolveSync(options)\n return result.fold(\n () => Left(ConfigErrorConstructor(options.candidates)),\n (v) => Right(v),\n )\n },\n\n resolveAllSync: (options: { readonly candidates: readonly string[] }): List<string> => {\n return List(\n options.candidates.reduce<readonly string[]>((acc, candidate) => {\n const expanded = tryExpandPath(candidate)\n if (expanded.isNone()) return acc\n const path = expanded.orThrow()\n return Fs.existsSync(path) ? [...acc, path] : acc\n }, []),\n )\n },\n}\n"],"mappings":"0NAQA,MAAM,EAAiB,GACN,EAAW,EAAU,CACtB,SACN,EAAe,IAAA,GAAU,CAC9B,GAAM,EAAO,EAAE,CACjB,CAGU,EAAiB,CAG5B,QAAS,KAAO,IAAoF,CAClG,IAAK,IAAM,KAAa,EAAQ,WAAY,CAC1C,IAAM,EAAW,EAAc,EAAU,CACzC,GAAI,EAAS,QAAQ,CAAE,SAEvB,IAAM,EAAe,MAAM,EAAG,OAAO,EAAS,SAAS,CAAC,CACpD,MAAa,OAAO,EACpB,EAAa,MACf,OAAO,EAAG,EAAS,CAGvB,OAAO,EAAG,EAAe,IAAA,GAAU,CAAC,EAGtC,gBAAiB,KAAO,IAA4E,CAClG,IAAM,EAAS,MAAM,EAAe,QAAQ,EAAQ,CACpD,GAAI,EAAO,OAAO,CAAE,OAAO,EAAI,EAAO,MAAM,CAE5C,IAAM,EAAW,EAAO,SAAS,CAKjC,OAJI,EAAS,QAAQ,CACZ,EAAG,EAAS,SAAS,CAAC,CAGxB,EAAIA,EAAuB,EAAQ,WAAW,CAAC,EAGxD,WAAY,KAAO,IAAkF,CACnG,IAAM,EAA2B,EAAQ,WAAW,QAA2B,EAAK,IAAc,CAChG,IAAM,EAAW,EAAc,EAAU,CAEzC,OADI,EAAS,QAAQ,CAAS,EACvB,CAAC,GAAG,EAAK,EAAS,SAAS,CAAC,EAClC,EAAE,CAAC,CAEA,EAAoB,EAAE,CAC5B,IAAK,IAAM,KAAY,EAAO,CAC5B,IAAM,EAAe,MAAM,EAAG,OAAO,EAAS,CAC1C,EAAa,MAAM,EAAI,EAAa,OACtC,EAAQ,KAAK,EAAS,CAI1B,OAAO,EAAG,EAAK,EAAQ,CAAC,EAK1B,YAAc,GAAwE,CACpF,IAAK,IAAM,KAAa,EAAQ,WAAY,CAC1C,IAAM,EAAW,EAAc,EAAU,CACrC,MAAS,QAAQ,EACjB,EAAG,WAAW,EAAS,SAAS,CAAC,CACnC,OAAO,EAGX,OAAO,EAAe,IAAA,GAAU,EAGlC,oBAAsB,GACL,EAAe,YAAY,EAAQ,CACpC,SACN,EAAKA,EAAuB,EAAQ,WAAW,CAAC,CACrD,GAAM,EAAM,EAAE,CAChB,CAGH,eAAiB,GACR,EACL,EAAQ,WAAW,QAA2B,EAAK,IAAc,CAC/D,IAAM,EAAW,EAAc,EAAU,CACzC,GAAI,EAAS,QAAQ,CAAE,OAAO,EAC9B,IAAM,EAAO,EAAS,SAAS,CAC/B,OAAO,EAAG,WAAW,EAAK,CAAG,CAAC,GAAG,EAAK,EAAK,CAAG,GAC7C,EAAE,CAAC,CACP,CAEJ"}
1
+ {"version":3,"file":"ConfigResolver.js","names":["ConfigErrorConstructor"],"sources":["../../src/config/ConfigResolver.ts"],"sourcesContent":["import type { Either, TaskResult } from \"functype\"\nimport { Err, Left, List, Ok, Option, Right } from \"functype\"\n\nimport type { ConfigError } from \"../errors/errors\"\nimport { ConfigError as ConfigErrorConstructor } from \"../errors/errors\"\nimport { Fs } from \"../fs/Fs\"\nimport { expandPath } from \"../path/PathExpander\"\n\nconst tryExpandPath = (candidate: string): Option<string> => {\n const result = expandPath(candidate)\n return result.fold(\n () => Option<string>(undefined),\n (v) => Option(v),\n )\n}\n\nexport const ConfigResolver = {\n // Async methods — return TaskResult<T>\n\n resolve: async (options: { readonly candidates: readonly string[] }): TaskResult<Option<string>> => {\n for (const candidate of options.candidates) {\n const expanded = tryExpandPath(candidate)\n if (expanded.isNone()) continue\n\n const existsResult = await Fs.exists(expanded.orThrow())\n if (existsResult.isErr()) continue\n if (existsResult.value) {\n return Ok(expanded)\n }\n }\n return Ok(Option<string>(undefined))\n },\n\n resolveRequired: async (options: { readonly candidates: readonly string[] }): TaskResult<string> => {\n const result = await ConfigResolver.resolve(options)\n if (result.isErr()) return Err(result.error)\n\n const optValue = result.orThrow()\n if (optValue.isSome()) {\n return Ok(optValue.orThrow())\n }\n\n return Err(ConfigErrorConstructor(options.candidates))\n },\n\n resolveAll: async (options: { readonly candidates: readonly string[] }): TaskResult<List<string>> => {\n const found: readonly string[] = options.candidates.reduce<readonly string[]>((acc, candidate) => {\n const expanded = tryExpandPath(candidate)\n if (expanded.isNone()) return acc\n return [...acc, expanded.orThrow()]\n }, [])\n\n const results: string[] = []\n for (const expanded of found) {\n const existsResult = await Fs.exists(expanded)\n if (existsResult.isOk() && existsResult.value) {\n results.push(expanded)\n }\n }\n\n return Ok(List(results))\n },\n\n // Sync methods — return Either<ConfigError, T>\n\n resolveSync: (options: { readonly candidates: readonly string[] }): Option<string> => {\n for (const candidate of options.candidates) {\n const expanded = tryExpandPath(candidate)\n if (expanded.isNone()) continue\n if (Fs.existsSync(expanded.orThrow())) {\n return expanded\n }\n }\n return Option<string>(undefined)\n },\n\n resolveRequiredSync: (options: { readonly candidates: readonly string[] }): Either<ConfigError, string> => {\n const result = ConfigResolver.resolveSync(options)\n return result.fold(\n () => Left(ConfigErrorConstructor(options.candidates)),\n (v) => Right(v),\n )\n },\n\n resolveAllSync: (options: { readonly candidates: readonly string[] }): List<string> => {\n return List(\n options.candidates.reduce<readonly string[]>((acc, candidate) => {\n const expanded = tryExpandPath(candidate)\n if (expanded.isNone()) return acc\n const path = expanded.orThrow()\n return Fs.existsSync(path) ? [...acc, path] : acc\n }, []),\n )\n },\n}\n"],"mappings":"0NAQA,MAAM,EAAiB,GACN,EAAW,CACd,EAAE,SACN,EAAe,IAAA,EAAS,EAC7B,GAAM,EAAO,CAAC,CACjB,EAGW,EAAiB,CAG5B,QAAS,KAAO,IAAoF,CAClG,IAAK,IAAM,KAAa,EAAQ,WAAY,CAC1C,IAAM,EAAW,EAAc,CAAS,EACxC,GAAI,EAAS,OAAO,EAAG,SAEvB,IAAM,EAAe,MAAM,EAAG,OAAO,EAAS,QAAQ,CAAC,EACnD,MAAa,MAAM,GACnB,EAAa,MACf,OAAO,EAAG,CAAQ,CAEtB,CACA,OAAO,EAAG,EAAe,IAAA,EAAS,CAAC,CACrC,EAEA,gBAAiB,KAAO,IAA4E,CAClG,IAAM,EAAS,MAAM,EAAe,QAAQ,CAAO,EACnD,GAAI,EAAO,MAAM,EAAG,OAAO,EAAI,EAAO,KAAK,EAE3C,IAAM,EAAW,EAAO,QAAQ,EAKhC,OAJI,EAAS,OAAO,EACX,EAAG,EAAS,QAAQ,CAAC,EAGvB,EAAIA,EAAuB,EAAQ,UAAU,CAAC,CACvD,EAEA,WAAY,KAAO,IAAkF,CACnG,IAAM,EAA2B,EAAQ,WAAW,QAA2B,EAAK,IAAc,CAChG,IAAM,EAAW,EAAc,CAAS,EAExC,OADI,EAAS,OAAO,EAAU,EACvB,CAAC,GAAG,EAAK,EAAS,QAAQ,CAAC,CACpC,EAAG,CAAC,CAAC,EAEC,EAAoB,CAAC,EAC3B,IAAK,IAAM,KAAY,EAAO,CAC5B,IAAM,EAAe,MAAM,EAAG,OAAO,CAAQ,EACzC,EAAa,KAAK,GAAK,EAAa,OACtC,EAAQ,KAAK,CAAQ,CAEzB,CAEA,OAAO,EAAG,EAAK,CAAO,CAAC,CACzB,EAIA,YAAc,GAAwE,CACpF,IAAK,IAAM,KAAa,EAAQ,WAAY,CAC1C,IAAM,EAAW,EAAc,CAAS,EACpC,MAAS,OAAO,GAChB,EAAG,WAAW,EAAS,QAAQ,CAAC,EAClC,OAAO,CAEX,CACA,OAAO,EAAe,IAAA,EAAS,CACjC,EAEA,oBAAsB,GACL,EAAe,YAAY,CAC9B,EAAE,SACN,EAAKA,EAAuB,EAAQ,UAAU,CAAC,EACpD,GAAM,EAAM,CAAC,CAChB,EAGF,eAAiB,GACR,EACL,EAAQ,WAAW,QAA2B,EAAK,IAAc,CAC/D,IAAM,EAAW,EAAc,CAAS,EACxC,GAAI,EAAS,OAAO,EAAG,OAAO,EAC9B,IAAM,EAAO,EAAS,QAAQ,EAC9B,OAAO,EAAG,WAAW,CAAI,EAAI,CAAC,GAAG,EAAK,CAAI,EAAI,CAChD,EAAG,CAAC,CAAC,CACP,CAEJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"Env.js","names":[],"sources":["../../src/env/Env.ts"],"sourcesContent":["import type { Either } from \"functype\"\nimport { Left, List, Option, Right } from \"functype\"\n\nimport { EnvError } from \"../errors/errors\"\n\nconst EnvConstructor = (name: string): Option<string> => Option(process.env[name])\n\nconst EnvCompanion = {\n get: (name: string): Option<string> => Option(process.env[name]),\n\n getRequired: (name: string): Either<EnvError, string> => {\n const value = process.env[name]\n return value !== undefined ? Right(value) : Left(EnvError(name))\n },\n\n getOrDefault: (name: string, defaultValue: string): string => process.env[name] ?? defaultValue,\n\n has: (name: string): boolean => process.env[name] !== undefined,\n\n entries: (): List<readonly [string, string]> => {\n const pairs: Readonly<Array<readonly [string, string]>> = Object.entries(process.env)\n .filter((entry): entry is [string, string] => entry[1] !== undefined)\n .map(([k, v]) => [k, v] as const)\n return List(pairs)\n },\n\n parse: <T>(name: string, parser: (value: string) => T): Either<EnvError, T> => {\n const value = process.env[name]\n if (value === undefined) {\n return Left(EnvError(name))\n }\n try {\n const parsed = parser(value)\n if (typeof parsed === \"number\" && isNaN(parsed)) {\n return Left(EnvError(name, `Cannot parse '${value}' as number for '${name}'`))\n }\n return Right(parsed)\n } catch (error) {\n return Left(\n EnvError(name, `Failed to parse '${name}': ${error instanceof Error ? error.message : String(error)}`),\n )\n }\n },\n}\n\nexport const Env: typeof EnvConstructor & typeof EnvCompanion = Object.assign(EnvConstructor, EnvCompanion)\n"],"mappings":"gHA6CA,MAAa,EAAmD,OAAO,OAxC/C,GAAiC,EAAO,QAAQ,IAAI,GAAM,CAE7D,CACnB,IAAM,GAAiC,EAAO,QAAQ,IAAI,GAAM,CAEhE,YAAc,GAA2C,CACvD,IAAM,EAAQ,QAAQ,IAAI,GAC1B,OAAO,IAAU,IAAA,GAA2B,EAAK,EAAS,EAAK,CAAC,CAAnC,EAAM,EAAM,EAG3C,cAAe,EAAc,IAAiC,QAAQ,IAAI,IAAS,EAEnF,IAAM,GAA0B,QAAQ,IAAI,KAAU,IAAA,GAEtD,YAIS,EAHmD,OAAO,QAAQ,QAAQ,IAAI,CAClF,OAAQ,GAAqC,EAAM,KAAO,IAAA,GAAU,CACpE,KAAK,CAAC,EAAG,KAAO,CAAC,EAAG,EAAE,CAAU,CACjB,CAGpB,OAAW,EAAc,IAAsD,CAC7E,IAAM,EAAQ,QAAQ,IAAI,GAC1B,GAAI,IAAU,IAAA,GACZ,OAAO,EAAK,EAAS,EAAK,CAAC,CAE7B,GAAI,CACF,IAAM,EAAS,EAAO,EAAM,CAI5B,OAHI,OAAO,GAAW,UAAY,MAAM,EAAO,CACtC,EAAK,EAAS,EAAM,iBAAiB,EAAM,mBAAmB,EAAK,GAAG,CAAC,CAEzE,EAAM,EAAO,OACb,EAAO,CACd,OAAO,EACL,EAAS,EAAM,oBAAoB,EAAK,KAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAAG,CACvG,GAGN,CAE0G"}
1
+ {"version":3,"file":"Env.js","names":[],"sources":["../../src/env/Env.ts"],"sourcesContent":["import type { Either } from \"functype\"\nimport { Left, List, Option, Right } from \"functype\"\n\nimport { EnvError } from \"../errors/errors\"\n\nconst EnvConstructor = (name: string): Option<string> => Option(process.env[name])\n\nconst EnvCompanion = {\n get: (name: string): Option<string> => Option(process.env[name]),\n\n getRequired: (name: string): Either<EnvError, string> => {\n const value = process.env[name]\n return value !== undefined ? Right(value) : Left(EnvError(name))\n },\n\n getOrDefault: (name: string, defaultValue: string): string => process.env[name] ?? defaultValue,\n\n has: (name: string): boolean => process.env[name] !== undefined,\n\n entries: (): List<readonly [string, string]> => {\n const pairs: Readonly<Array<readonly [string, string]>> = Object.entries(process.env)\n .filter((entry): entry is [string, string] => entry[1] !== undefined)\n .map(([k, v]) => [k, v] as const)\n return List(pairs)\n },\n\n parse: <T>(name: string, parser: (value: string) => T): Either<EnvError, T> => {\n const value = process.env[name]\n if (value === undefined) {\n return Left(EnvError(name))\n }\n try {\n const parsed = parser(value)\n if (typeof parsed === \"number\" && isNaN(parsed)) {\n return Left(EnvError(name, `Cannot parse '${value}' as number for '${name}'`))\n }\n return Right(parsed)\n } catch (error) {\n return Left(\n EnvError(name, `Failed to parse '${name}': ${error instanceof Error ? error.message : String(error)}`),\n )\n }\n },\n}\n\nexport const Env: typeof EnvConstructor & typeof EnvCompanion = Object.assign(EnvConstructor, EnvCompanion)\n"],"mappings":"gHA6CA,MAAa,EAAmD,OAAO,OAxC/C,GAAiC,EAAO,QAAQ,IAAI,EAAK,EAwCa,CArC5F,IAAM,GAAiC,EAAO,QAAQ,IAAI,EAAK,EAE/D,YAAc,GAA2C,CACvD,IAAM,EAAQ,QAAQ,IAAI,GAC1B,OAAO,IAAU,IAAA,GAA2B,EAAK,EAAS,CAAI,CAAC,EAAlC,EAAM,CAAK,CAC1C,EAEA,cAAe,EAAc,IAAiC,QAAQ,IAAI,IAAS,EAEnF,IAAM,GAA0B,QAAQ,IAAI,KAAU,IAAA,GAEtD,YAIS,EAHmD,OAAO,QAAQ,QAAQ,GAAG,EACjF,OAAQ,GAAqC,EAAM,KAAO,IAAA,EAAS,EACnE,KAAK,CAAC,EAAG,KAAO,CAAC,EAAG,CAAC,CACR,CAAC,EAGnB,OAAW,EAAc,IAAsD,CAC7E,IAAM,EAAQ,QAAQ,IAAI,GAC1B,GAAI,IAAU,IAAA,GACZ,OAAO,EAAK,EAAS,CAAI,CAAC,EAE5B,GAAI,CACF,IAAM,EAAS,EAAO,CAAK,EAI3B,OAHI,OAAO,GAAW,UAAY,MAAM,CAAM,EACrC,EAAK,EAAS,EAAM,iBAAiB,EAAM,mBAAmB,EAAK,EAAE,CAAC,EAExE,EAAM,CAAM,CACrB,OAAS,EAAO,CACd,OAAO,EACL,EAAS,EAAM,oBAAoB,EAAK,KAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,GAAG,CACvG,CACF,CACF,CAG4F,CAAY"}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":[],"sources":["../../src/errors/errors.ts"],"sourcesContent":["export type EnvError = {\n readonly _tag: \"EnvError\"\n readonly variable: string\n readonly message: string\n}\n\nexport type PathError = {\n readonly _tag: \"PathError\"\n readonly path: string\n readonly reason: \"unresolved_variable\" | \"invalid_path\"\n readonly message: string\n}\n\nexport type FsError = {\n readonly _tag: \"FsError\"\n readonly path: string\n readonly operation: string\n readonly cause: Error\n readonly message: string\n}\n\nexport type ConfigError = {\n readonly _tag: \"ConfigError\"\n readonly candidates: readonly string[]\n readonly message: string\n}\n\nexport type ProcessError = {\n readonly _tag: \"ProcessError\"\n readonly command: string\n readonly exitCode: number | null\n readonly stderr: string\n readonly message: string\n}\n\nexport type OsError = EnvError | PathError | FsError | ConfigError | ProcessError\n\nexport const EnvError = (variable: string, message?: string): EnvError => ({\n _tag: \"EnvError\",\n variable,\n message: message ?? `Environment variable '${variable}' is not set`,\n})\n\nexport const PathError = (path: string, reason: PathError[\"reason\"], message?: string): PathError => ({\n _tag: \"PathError\",\n path,\n reason,\n message:\n message ?? (reason === \"unresolved_variable\" ? `Unresolved variable in path: ${path}` : `Invalid path: ${path}`),\n})\n\nexport const FsError = (path: string, operation: string, cause: Error): FsError => ({\n _tag: \"FsError\",\n path,\n operation,\n cause,\n message: `${operation} failed for '${path}': ${cause.message}`,\n})\n\nexport const ConfigError = (candidates: readonly string[], message?: string): ConfigError => ({\n _tag: \"ConfigError\",\n candidates,\n message: message ?? `No config file found among candidates: ${candidates.join(\", \")}`,\n})\n\nexport const ProcessError = (\n command: string,\n exitCode: number | null,\n stderr: string,\n message?: string,\n): ProcessError => ({\n _tag: \"ProcessError\",\n command,\n exitCode,\n stderr,\n message: message ?? `Command '${command}' failed (exit ${exitCode}): ${stderr}`,\n})\n"],"mappings":"AAqCA,MAAa,GAAY,EAAkB,KAAgC,CACzE,KAAM,WACN,WACA,QAAS,GAAW,yBAAyB,EAAS,cACvD,EAEY,GAAa,EAAc,EAA6B,KAAiC,CACpG,KAAM,YACN,OACA,SACA,QACE,IAAY,IAAW,sBAAwB,gCAAgC,IAAS,iBAAiB,KAC5G,EAEY,GAAW,EAAc,EAAmB,KAA2B,CAClF,KAAM,UACN,OACA,YACA,QACA,QAAS,GAAG,EAAU,eAAe,EAAK,KAAK,EAAM,UACtD,EAEY,GAAe,EAA+B,KAAmC,CAC5F,KAAM,cACN,aACA,QAAS,GAAW,0CAA0C,EAAW,KAAK,KAAK,GACpF,EAEY,GACX,EACA,EACA,EACA,KACkB,CAClB,KAAM,eACN,UACA,WACA,SACA,QAAS,GAAW,YAAY,EAAQ,iBAAiB,EAAS,KAAK,IACxE"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../../src/errors/errors.ts"],"sourcesContent":["export type EnvError = {\n readonly _tag: \"EnvError\"\n readonly variable: string\n readonly message: string\n}\n\nexport type PathError = {\n readonly _tag: \"PathError\"\n readonly path: string\n readonly reason: \"unresolved_variable\" | \"invalid_path\"\n readonly message: string\n}\n\nexport type FsError = {\n readonly _tag: \"FsError\"\n readonly path: string\n readonly operation: string\n readonly cause: Error\n readonly message: string\n}\n\nexport type ConfigError = {\n readonly _tag: \"ConfigError\"\n readonly candidates: readonly string[]\n readonly message: string\n}\n\nexport type ProcessError = {\n readonly _tag: \"ProcessError\"\n readonly command: string\n readonly exitCode: number | null\n readonly stderr: string\n readonly message: string\n}\n\nexport type OsError = EnvError | PathError | FsError | ConfigError | ProcessError\n\nexport const EnvError = (variable: string, message?: string): EnvError => ({\n _tag: \"EnvError\",\n variable,\n message: message ?? `Environment variable '${variable}' is not set`,\n})\n\nexport const PathError = (path: string, reason: PathError[\"reason\"], message?: string): PathError => ({\n _tag: \"PathError\",\n path,\n reason,\n message:\n message ?? (reason === \"unresolved_variable\" ? `Unresolved variable in path: ${path}` : `Invalid path: ${path}`),\n})\n\nexport const FsError = (path: string, operation: string, cause: Error): FsError => ({\n _tag: \"FsError\",\n path,\n operation,\n cause,\n message: `${operation} failed for '${path}': ${cause.message}`,\n})\n\nexport const ConfigError = (candidates: readonly string[], message?: string): ConfigError => ({\n _tag: \"ConfigError\",\n candidates,\n message: message ?? `No config file found among candidates: ${candidates.join(\", \")}`,\n})\n\nexport const ProcessError = (\n command: string,\n exitCode: number | null,\n stderr: string,\n message?: string,\n): ProcessError => ({\n _tag: \"ProcessError\",\n command,\n exitCode,\n stderr,\n message: message ?? `Command '${command}' failed (exit ${exitCode}): ${stderr}`,\n})\n"],"mappings":"AAqCA,MAAa,GAAY,EAAkB,KAAgC,CACzE,KAAM,WACN,WACA,QAAS,GAAW,yBAAyB,EAAS,aACxD,GAEa,GAAa,EAAc,EAA6B,KAAiC,CACpG,KAAM,YACN,OACA,SACA,QACE,IAAY,IAAW,sBAAwB,gCAAgC,IAAS,iBAAiB,IAC7G,GAEa,GAAW,EAAc,EAAmB,KAA2B,CAClF,KAAM,UACN,OACA,YACA,QACA,QAAS,GAAG,EAAU,eAAe,EAAK,KAAK,EAAM,SACvD,GAEa,GAAe,EAA+B,KAAmC,CAC5F,KAAM,cACN,aACA,QAAS,GAAW,0CAA0C,EAAW,KAAK,IAAI,GACpF,GAEa,GACX,EACA,EACA,EACA,KACkB,CAClB,KAAM,eACN,UACA,WACA,SACA,QAAS,GAAW,YAAY,EAAQ,iBAAiB,EAAS,KAAK,GACzE"}
package/dist/fs/Fs.js CHANGED
@@ -1,2 +1,2 @@
1
- import{FsError as e}from"../errors/errors.js";import{Err as t,Left as n,List as r,Ok as i,Option as a,Right as o}from"functype";import*as s from"node:fs";import*as c from"node:fs/promises";const l=e=>({size:e.size,isFile:e.isFile(),isDirectory:e.isDirectory(),isSymbolicLink:e.isSymbolicLink(),createdAt:e.birthtime,modifiedAt:e.mtime,accessedAt:e.atime,permissions:e.mode}),u=(t,n,r)=>e(t,n,r instanceof Error?r:Error(String(r))),d=(e,t)=>{let n=t.replace(/\./g,`\\.`).replace(/\*\*\//g,`{{GLOBSTAR}}`).replace(/\*\*/g,`{{GLOBSTAR}}`).replace(/\*/g,`[^/]*`).replace(/\{\{GLOBSTAR\}\}/g,`(?:.*/)?`);return RegExp(`^${n}$`).test(e)},f={exists:async e=>{try{return await c.access(e),i(!0)}catch{return i(!1)}},readFile:async(e,n=`utf8`)=>{try{return i(await c.readFile(e,{encoding:n}))}catch(n){return t(u(e,`readFile`,n))}},readFileOpt:async(e,n=`utf8`)=>{try{return i(a(await c.readFile(e,{encoding:n})))}catch(n){return n instanceof Error&&`code`in n&&n.code===`ENOENT`?i(a(void 0)):t(u(e,`readFile`,n))}},stat:async e=>{try{return i(l(await c.stat(e)))}catch(n){return t(u(e,`stat`,n))}},copyFile:async(e,n)=>{try{return await c.copyFile(e,n),i(void 0)}catch(n){return t(u(e,`copyFile`,n))}},rename:async(e,n)=>{try{return await c.rename(e,n),i(void 0)}catch(n){return t(u(e,`rename`,n))}},readdir:async e=>{try{return i(r(await c.readdir(e)))}catch(n){return t(u(e,`readdir`,n))}},glob:async(e,n)=>{try{return i(r((await c.readdir(e,{recursive:!0,encoding:`utf8`})).filter(e=>d(e,n))))}catch(n){return t(u(e,`glob`,n))}},writeFile:async(e,n,r=`utf8`)=>{try{return await c.writeFile(e,n,{encoding:r}),i(void 0)}catch(n){return t(u(e,`writeFile`,n))}},mkdir:async(e,n)=>{try{return await c.mkdir(e,n),i(void 0)}catch(n){return t(u(e,`mkdir`,n))}},existsSync:e=>{try{return s.accessSync(e),!0}catch{return!1}},readFileSync:(e,t=`utf8`)=>{try{return o(s.readFileSync(e,{encoding:t}))}catch(t){return n(u(e,`readFileSync`,t))}},readFileOptSync:(e,t=`utf8`)=>{try{return o(a(s.readFileSync(e,{encoding:t})))}catch(t){return t instanceof Error&&`code`in t&&t.code===`ENOENT`?o(a(void 0)):n(u(e,`readFileOptSync`,t))}},statSync:e=>{try{return o(l(s.statSync(e)))}catch(t){return n(u(e,`statSync`,t))}},copyFileSync:(e,t)=>{try{return s.copyFileSync(e,t),o(void 0)}catch(t){return n(u(e,`copyFileSync`,t))}},renameSync:(e,t)=>{try{return s.renameSync(e,t),o(void 0)}catch(t){return n(u(e,`renameSync`,t))}},readdirSync:e=>{try{return o(r(s.readdirSync(e)))}catch(t){return n(u(e,`readdirSync`,t))}},writeFileSync:(e,t,r=`utf8`)=>{try{return s.writeFileSync(e,t,{encoding:r}),o(void 0)}catch(t){return n(u(e,`writeFileSync`,t))}},mkdirSync:(e,t)=>{try{return s.mkdirSync(e,t),o(void 0)}catch(t){return n(u(e,`mkdirSync`,t))}},unlink:async e=>{try{return await c.unlink(e),i(void 0)}catch(n){return t(u(e,`unlink`,n))}},unlinkSync:e=>{try{return s.unlinkSync(e),o(void 0)}catch(t){return n(u(e,`unlinkSync`,t))}}};export{f as Fs};
1
+ import{FsError as e}from"../errors/errors.js";import{Err as t,Left as n,List as r,Ok as i,Option as a,Right as o}from"functype";import*as s from"node:fs";import*as c from"node:fs/promises";const l=e=>({size:e.size,isFile:e.isFile(),isDirectory:e.isDirectory(),isSymbolicLink:e.isSymbolicLink(),createdAt:e.birthtime,modifiedAt:e.mtime,accessedAt:e.atime,permissions:e.mode}),u=(t,n,r)=>e(t,n,r instanceof Error?r:Error(String(r))),d=(e,t)=>{let n=t.replace(/[\\^$+?.()|[\]{}]/g,`\\$&`).replace(/\*\*\//g,`{{GLOBSTAR}}`).replace(/\*\*/g,`{{GLOBSTAR}}`).replace(/\*/g,`[^/]*`).replace(/\{\{GLOBSTAR\}\}/g,`(?:.*/)?`);return RegExp(`^${n}$`).test(e)},f={exists:async e=>{try{return await c.access(e),i(!0)}catch{return i(!1)}},readFile:async(e,n=`utf8`)=>{try{return i(await c.readFile(e,{encoding:n}))}catch(n){return t(u(e,`readFile`,n))}},readFileOpt:async(e,n=`utf8`)=>{try{return i(a(await c.readFile(e,{encoding:n})))}catch(n){return n instanceof Error&&`code`in n&&n.code===`ENOENT`?i(a(void 0)):t(u(e,`readFile`,n))}},stat:async e=>{try{return i(l(await c.stat(e)))}catch(n){return t(u(e,`stat`,n))}},copyFile:async(e,n)=>{try{return await c.copyFile(e,n),i(void 0)}catch(n){return t(u(e,`copyFile`,n))}},rename:async(e,n)=>{try{return await c.rename(e,n),i(void 0)}catch(n){return t(u(e,`rename`,n))}},readdir:async e=>{try{return i(r(await c.readdir(e)))}catch(n){return t(u(e,`readdir`,n))}},glob:async(e,n)=>{try{return i(r((await c.readdir(e,{recursive:!0,encoding:`utf8`})).filter(e=>d(e,n))))}catch(n){return t(u(e,`glob`,n))}},writeFile:async(e,n,r=`utf8`)=>{try{return await c.writeFile(e,n,{encoding:r}),i(void 0)}catch(n){return t(u(e,`writeFile`,n))}},mkdir:async(e,n)=>{try{return await c.mkdir(e,n),i(void 0)}catch(n){return t(u(e,`mkdir`,n))}},existsSync:e=>{try{return s.accessSync(e),!0}catch{return!1}},readFileSync:(e,t=`utf8`)=>{try{return o(s.readFileSync(e,{encoding:t}))}catch(t){return n(u(e,`readFileSync`,t))}},readFileOptSync:(e,t=`utf8`)=>{try{return o(a(s.readFileSync(e,{encoding:t})))}catch(t){return t instanceof Error&&`code`in t&&t.code===`ENOENT`?o(a(void 0)):n(u(e,`readFileOptSync`,t))}},statSync:e=>{try{return o(l(s.statSync(e)))}catch(t){return n(u(e,`statSync`,t))}},copyFileSync:(e,t)=>{try{return s.copyFileSync(e,t),o(void 0)}catch(t){return n(u(e,`copyFileSync`,t))}},renameSync:(e,t)=>{try{return s.renameSync(e,t),o(void 0)}catch(t){return n(u(e,`renameSync`,t))}},readdirSync:e=>{try{return o(r(s.readdirSync(e)))}catch(t){return n(u(e,`readdirSync`,t))}},writeFileSync:(e,t,r=`utf8`)=>{try{return s.writeFileSync(e,t,{encoding:r}),o(void 0)}catch(t){return n(u(e,`writeFileSync`,t))}},mkdirSync:(e,t)=>{try{return s.mkdirSync(e,t),o(void 0)}catch(t){return n(u(e,`mkdirSync`,t))}},unlink:async e=>{try{return await c.unlink(e),i(void 0)}catch(n){return t(u(e,`unlink`,n))}},unlinkSync:e=>{try{return s.unlinkSync(e),o(void 0)}catch(t){return n(u(e,`unlinkSync`,t))}}};export{f as Fs};
2
2
  //# sourceMappingURL=Fs.js.map
package/dist/fs/Fs.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Fs.js","names":[],"sources":["../../src/fs/Fs.ts"],"sourcesContent":["import * as fsSync from \"node:fs\"\nimport * as fs from \"node:fs/promises\"\n\nimport type { Either, TaskResult } from \"functype\"\nimport { Err, Left, List, Ok, Option, Right } from \"functype\"\n\nimport { FsError } from \"../errors/errors\"\n\nexport type FileInfo = {\n readonly size: number\n readonly isFile: boolean\n readonly isDirectory: boolean\n readonly isSymbolicLink: boolean\n readonly createdAt: Date\n readonly modifiedAt: Date\n readonly accessedAt: Date\n readonly permissions: number\n}\n\nconst toFileInfo = (stats: fsSync.Stats): FileInfo => ({\n size: stats.size,\n isFile: stats.isFile(),\n isDirectory: stats.isDirectory(),\n isSymbolicLink: stats.isSymbolicLink(),\n createdAt: stats.birthtime,\n modifiedAt: stats.mtime,\n accessedAt: stats.atime,\n permissions: stats.mode,\n})\n\nconst toFsError = (p: string, op: string, error: unknown): FsError =>\n FsError(p, op, error instanceof Error ? error : new Error(String(error)))\n\nconst matchGlob = (filePath: string, pattern: string): boolean => {\n const regex = pattern\n .replace(/\\./g, \"\\\\.\")\n .replace(/\\*\\*\\//g, \"{{GLOBSTAR}}\")\n .replace(/\\*\\*/g, \"{{GLOBSTAR}}\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/\\{\\{GLOBSTAR\\}\\}/g, \"(?:.*/)?\")\n return new RegExp(`^${regex}$`).test(filePath)\n}\n\nexport const Fs = {\n // Async methods — return TaskResult<T>\n\n exists: async (p: string): TaskResult<boolean> => {\n try {\n await fs.access(p)\n return Ok(true)\n } catch {\n return Ok(false)\n }\n },\n\n readFile: async (p: string, encoding: BufferEncoding = \"utf8\"): TaskResult<string> => {\n try {\n return Ok(await fs.readFile(p, { encoding }))\n } catch (error) {\n return Err(toFsError(p, \"readFile\", error))\n }\n },\n\n readFileOpt: async (p: string, encoding: BufferEncoding = \"utf8\"): TaskResult<Option<string>> => {\n try {\n return Ok(Option(await fs.readFile(p, { encoding })))\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return Ok(Option<string>(undefined))\n }\n return Err(toFsError(p, \"readFile\", error))\n }\n },\n\n stat: async (p: string): TaskResult<FileInfo> => {\n try {\n return Ok(toFileInfo(await fs.stat(p)))\n } catch (error) {\n return Err(toFsError(p, \"stat\", error))\n }\n },\n\n copyFile: async (src: string, dest: string): TaskResult<void> => {\n try {\n await fs.copyFile(src, dest)\n return Ok(undefined as void)\n } catch (error) {\n return Err(toFsError(src, \"copyFile\", error))\n }\n },\n\n rename: async (oldPath: string, newPath: string): TaskResult<void> => {\n try {\n await fs.rename(oldPath, newPath)\n return Ok(undefined as void)\n } catch (error) {\n return Err(toFsError(oldPath, \"rename\", error))\n }\n },\n\n readdir: async (p: string): TaskResult<List<string>> => {\n try {\n return Ok(List(await fs.readdir(p)))\n } catch (error) {\n return Err(toFsError(p, \"readdir\", error))\n }\n },\n\n glob: async (dir: string, pattern: string): TaskResult<List<string>> => {\n try {\n const entries = await fs.readdir(dir, { recursive: true, encoding: \"utf8\" })\n const matched = entries.filter((entry) => matchGlob(entry, pattern))\n return Ok(List(matched))\n } catch (error) {\n return Err(toFsError(dir, \"glob\", error))\n }\n },\n\n writeFile: async (p: string, data: string, encoding: BufferEncoding = \"utf8\"): TaskResult<void> => {\n try {\n await fs.writeFile(p, data, { encoding })\n return Ok(undefined as void)\n } catch (error) {\n return Err(toFsError(p, \"writeFile\", error))\n }\n },\n\n mkdir: async (p: string, options?: { recursive?: boolean }): TaskResult<void> => {\n try {\n await fs.mkdir(p, options)\n return Ok(undefined as void)\n } catch (error) {\n return Err(toFsError(p, \"mkdir\", error))\n }\n },\n\n // Sync methods — return Either<FsError, T>\n\n existsSync: (p: string): boolean => {\n try {\n fsSync.accessSync(p)\n return true\n } catch {\n return false\n }\n },\n\n readFileSync: (p: string, encoding: BufferEncoding = \"utf8\"): Either<FsError, string> => {\n try {\n return Right(fsSync.readFileSync(p, { encoding }))\n } catch (error) {\n return Left(toFsError(p, \"readFileSync\", error))\n }\n },\n\n readFileOptSync: (p: string, encoding: BufferEncoding = \"utf8\"): Either<FsError, Option<string>> => {\n try {\n return Right(Option(fsSync.readFileSync(p, { encoding })))\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return Right(Option<string>(undefined))\n }\n return Left(toFsError(p, \"readFileOptSync\", error))\n }\n },\n\n statSync: (p: string): Either<FsError, FileInfo> => {\n try {\n return Right(toFileInfo(fsSync.statSync(p)))\n } catch (error) {\n return Left(toFsError(p, \"statSync\", error))\n }\n },\n\n copyFileSync: (src: string, dest: string): Either<FsError, void> => {\n try {\n fsSync.copyFileSync(src, dest)\n return Right(undefined as void)\n } catch (error) {\n return Left(toFsError(src, \"copyFileSync\", error))\n }\n },\n\n renameSync: (oldPath: string, newPath: string): Either<FsError, void> => {\n try {\n fsSync.renameSync(oldPath, newPath)\n return Right(undefined as void)\n } catch (error) {\n return Left(toFsError(oldPath, \"renameSync\", error))\n }\n },\n\n readdirSync: (p: string): Either<FsError, List<string>> => {\n try {\n return Right(List(fsSync.readdirSync(p)))\n } catch (error) {\n return Left(toFsError(p, \"readdirSync\", error))\n }\n },\n\n writeFileSync: (p: string, data: string, encoding: BufferEncoding = \"utf8\"): Either<FsError, void> => {\n try {\n fsSync.writeFileSync(p, data, { encoding })\n return Right(undefined as void)\n } catch (error) {\n return Left(toFsError(p, \"writeFileSync\", error))\n }\n },\n\n mkdirSync: (p: string, options?: { recursive?: boolean }): Either<FsError, void> => {\n try {\n fsSync.mkdirSync(p, options)\n return Right(undefined as void)\n } catch (error) {\n return Left(toFsError(p, \"mkdirSync\", error))\n }\n },\n\n unlink: async (p: string): TaskResult<void> => {\n try {\n await fs.unlink(p)\n return Ok(undefined as void)\n } catch (error) {\n return Err(toFsError(p, \"unlink\", error))\n }\n },\n\n unlinkSync: (p: string): Either<FsError, void> => {\n try {\n fsSync.unlinkSync(p)\n return Right(undefined as void)\n } catch (error) {\n return Left(toFsError(p, \"unlinkSync\", error))\n }\n },\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Fs.js","names":[],"sources":["../../src/fs/Fs.ts"],"sourcesContent":["import * as fsSync from \"node:fs\"\nimport * as fs from \"node:fs/promises\"\n\nimport type { Either, TaskResult } from \"functype\"\nimport { Err, Left, List, Ok, Option, Right } from \"functype\"\n\nimport { FsError } from \"../errors/errors\"\n\nexport type FileInfo = {\n readonly size: number\n readonly isFile: boolean\n readonly isDirectory: boolean\n readonly isSymbolicLink: boolean\n readonly createdAt: Date\n readonly modifiedAt: Date\n readonly accessedAt: Date\n readonly permissions: number\n}\n\nconst toFileInfo = (stats: fsSync.Stats): FileInfo => ({\n size: stats.size,\n isFile: stats.isFile(),\n isDirectory: stats.isDirectory(),\n isSymbolicLink: stats.isSymbolicLink(),\n createdAt: stats.birthtime,\n modifiedAt: stats.mtime,\n accessedAt: stats.atime,\n permissions: stats.mode,\n})\n\nconst toFsError = (p: string, op: string, error: unknown): FsError =>\n FsError(p, op, error instanceof Error ? error : new Error(String(error)))\n\nconst matchGlob = (filePath: string, pattern: string): boolean => {\n // Escape every regex metachar EXCEPT '*' first, so the subsequent\n // '*' transformations are the only special characters in the output.\n // Order matters: backslashes must be escaped before any '\\\\' insertion below.\n const escaped = pattern.replace(/[\\\\^$+?.()|[\\]{}]/g, \"\\\\$&\")\n const regex = escaped\n .replace(/\\*\\*\\//g, \"{{GLOBSTAR}}\")\n .replace(/\\*\\*/g, \"{{GLOBSTAR}}\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/\\{\\{GLOBSTAR\\}\\}/g, \"(?:.*/)?\")\n return new RegExp(`^${regex}$`).test(filePath)\n}\n\nexport const Fs = {\n // Async methods — return TaskResult<T>\n\n exists: async (p: string): TaskResult<boolean> => {\n try {\n await fs.access(p)\n return Ok(true)\n } catch {\n return Ok(false)\n }\n },\n\n readFile: async (p: string, encoding: BufferEncoding = \"utf8\"): TaskResult<string> => {\n try {\n return Ok(await fs.readFile(p, { encoding }))\n } catch (error) {\n return Err(toFsError(p, \"readFile\", error))\n }\n },\n\n readFileOpt: async (p: string, encoding: BufferEncoding = \"utf8\"): TaskResult<Option<string>> => {\n try {\n return Ok(Option(await fs.readFile(p, { encoding })))\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return Ok(Option<string>(undefined))\n }\n return Err(toFsError(p, \"readFile\", error))\n }\n },\n\n stat: async (p: string): TaskResult<FileInfo> => {\n try {\n return Ok(toFileInfo(await fs.stat(p)))\n } catch (error) {\n return Err(toFsError(p, \"stat\", error))\n }\n },\n\n copyFile: async (src: string, dest: string): TaskResult<void> => {\n try {\n await fs.copyFile(src, dest)\n return Ok(undefined as void)\n } catch (error) {\n return Err(toFsError(src, \"copyFile\", error))\n }\n },\n\n rename: async (oldPath: string, newPath: string): TaskResult<void> => {\n try {\n await fs.rename(oldPath, newPath)\n return Ok(undefined as void)\n } catch (error) {\n return Err(toFsError(oldPath, \"rename\", error))\n }\n },\n\n readdir: async (p: string): TaskResult<List<string>> => {\n try {\n return Ok(List(await fs.readdir(p)))\n } catch (error) {\n return Err(toFsError(p, \"readdir\", error))\n }\n },\n\n glob: async (dir: string, pattern: string): TaskResult<List<string>> => {\n try {\n const entries = await fs.readdir(dir, { recursive: true, encoding: \"utf8\" })\n const matched = entries.filter((entry) => matchGlob(entry, pattern))\n return Ok(List(matched))\n } catch (error) {\n return Err(toFsError(dir, \"glob\", error))\n }\n },\n\n writeFile: async (p: string, data: string, encoding: BufferEncoding = \"utf8\"): TaskResult<void> => {\n try {\n await fs.writeFile(p, data, { encoding })\n return Ok(undefined as void)\n } catch (error) {\n return Err(toFsError(p, \"writeFile\", error))\n }\n },\n\n mkdir: async (p: string, options?: { recursive?: boolean }): TaskResult<void> => {\n try {\n await fs.mkdir(p, options)\n return Ok(undefined as void)\n } catch (error) {\n return Err(toFsError(p, \"mkdir\", error))\n }\n },\n\n // Sync methods — return Either<FsError, T>\n\n existsSync: (p: string): boolean => {\n try {\n fsSync.accessSync(p)\n return true\n } catch {\n return false\n }\n },\n\n readFileSync: (p: string, encoding: BufferEncoding = \"utf8\"): Either<FsError, string> => {\n try {\n return Right(fsSync.readFileSync(p, { encoding }))\n } catch (error) {\n return Left(toFsError(p, \"readFileSync\", error))\n }\n },\n\n readFileOptSync: (p: string, encoding: BufferEncoding = \"utf8\"): Either<FsError, Option<string>> => {\n try {\n return Right(Option(fsSync.readFileSync(p, { encoding })))\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return Right(Option<string>(undefined))\n }\n return Left(toFsError(p, \"readFileOptSync\", error))\n }\n },\n\n statSync: (p: string): Either<FsError, FileInfo> => {\n try {\n return Right(toFileInfo(fsSync.statSync(p)))\n } catch (error) {\n return Left(toFsError(p, \"statSync\", error))\n }\n },\n\n copyFileSync: (src: string, dest: string): Either<FsError, void> => {\n try {\n fsSync.copyFileSync(src, dest)\n return Right(undefined as void)\n } catch (error) {\n return Left(toFsError(src, \"copyFileSync\", error))\n }\n },\n\n renameSync: (oldPath: string, newPath: string): Either<FsError, void> => {\n try {\n fsSync.renameSync(oldPath, newPath)\n return Right(undefined as void)\n } catch (error) {\n return Left(toFsError(oldPath, \"renameSync\", error))\n }\n },\n\n readdirSync: (p: string): Either<FsError, List<string>> => {\n try {\n return Right(List(fsSync.readdirSync(p)))\n } catch (error) {\n return Left(toFsError(p, \"readdirSync\", error))\n }\n },\n\n writeFileSync: (p: string, data: string, encoding: BufferEncoding = \"utf8\"): Either<FsError, void> => {\n try {\n fsSync.writeFileSync(p, data, { encoding })\n return Right(undefined as void)\n } catch (error) {\n return Left(toFsError(p, \"writeFileSync\", error))\n }\n },\n\n mkdirSync: (p: string, options?: { recursive?: boolean }): Either<FsError, void> => {\n try {\n fsSync.mkdirSync(p, options)\n return Right(undefined as void)\n } catch (error) {\n return Left(toFsError(p, \"mkdirSync\", error))\n }\n },\n\n unlink: async (p: string): TaskResult<void> => {\n try {\n await fs.unlink(p)\n return Ok(undefined as void)\n } catch (error) {\n return Err(toFsError(p, \"unlink\", error))\n }\n },\n\n unlinkSync: (p: string): Either<FsError, void> => {\n try {\n fsSync.unlinkSync(p)\n return Right(undefined as void)\n } catch (error) {\n return Left(toFsError(p, \"unlinkSync\", error))\n }\n },\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{PathError as e}from"../errors/errors.js";import{Left as t,Right as n}from"functype";import*as r from"node:os";import*as i from"node:path";const a=e=>e===`~`?r.homedir():e.startsWith(`~/`)||e.startsWith(`~\\`)?i.join(r.homedir(),e.slice(2)):e,o=r=>{let i=[],a=r.replace(/\$\{([^}]+)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g,(e,t,n)=>{let r=t??n??``,a=process.env[r];return a===void 0?(i.push(r),e):a});return i.length>0?t(e(r,`unresolved_variable`,`Unresolved variables: ${i.join(`, `)}`)):n(a)},s=e=>{let t=o(a(e));return t.isLeft()?t:n(i.resolve(t.orThrow()))},c={expand:s,expandTilde:a,expandVars:o,join:(...e)=>i.join(...e),resolve:(...e)=>i.resolve(...e),dirname:e=>i.dirname(e),basename:(e,t)=>i.basename(e,t),extname:e=>i.extname(e),isAbsolute:e=>i.isAbsolute(e)};export{c as Path,s as expandPath,a as expandTilde,o as expandVars};
1
+ import{PathError as e}from"../errors/errors.js";import{Left as t,Right as n}from"functype";import*as r from"node:os";import*as i from"node:path";const a=e=>e===`~`?r.homedir():e.startsWith(`~/`)||e.startsWith(`~\\`)?i.join(r.homedir(),e.slice(2)):e,o=r=>{let i=[],a=r.replace(/\$(?:\{([^}$]+)\}|([A-Za-z_][A-Za-z0-9_]*))/g,(e,t,n)=>{let r=t??n??``,a=process.env[r];return a===void 0?(i.push(r),e):a});return i.length>0?t(e(r,`unresolved_variable`,`Unresolved variables: ${i.join(`, `)}`)):n(a)},s=e=>{let t=o(a(e));return t.isLeft()?t:n(i.resolve(t.orThrow()))},c={expand:s,expandTilde:a,expandVars:o,join:(...e)=>i.join(...e),resolve:(...e)=>i.resolve(...e),dirname:e=>i.dirname(e),basename:(e,t)=>i.basename(e,t),extname:e=>i.extname(e),isAbsolute:e=>i.isAbsolute(e)};export{c as Path,s as expandPath,a as expandTilde,o as expandVars};
2
2
  //# sourceMappingURL=PathExpander.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PathExpander.js","names":[],"sources":["../../src/path/PathExpander.ts"],"sourcesContent":["import * as os from \"node:os\"\nimport * as nodePath from \"node:path\"\n\nimport type { Either } from \"functype\"\nimport { Left, Right } from \"functype\"\n\nimport { PathError } from \"../errors/errors\"\n\nexport const expandTilde = (p: string): string => {\n if (p === \"~\") return os.homedir()\n if (p.startsWith(\"~/\") || p.startsWith(\"~\\\\\")) return nodePath.join(os.homedir(), p.slice(2))\n return p\n}\n\nexport const expandVars = (p: string): Either<PathError, string> => {\n const unresolvedVars: string[] = []\n const result = p.replace(\n /\\$\\{([^}]+)\\}|\\$([A-Za-z_][A-Za-z0-9_]*)/g,\n (_match, braced: string | undefined, bare: string | undefined) => {\n const varName = braced ?? bare ?? \"\"\n const value = process.env[varName]\n if (value === undefined) {\n unresolvedVars.push(varName)\n return _match\n }\n return value\n },\n )\n\n if (unresolvedVars.length > 0) {\n return Left(PathError(p, \"unresolved_variable\", `Unresolved variables: ${unresolvedVars.join(\", \")}`))\n }\n\n return Right(result)\n}\n\nexport const expandPath = (p: string): Either<PathError, string> => {\n const tildeExpanded = expandTilde(p)\n const varsResult = expandVars(tildeExpanded)\n if (varsResult.isLeft()) return varsResult\n return Right(nodePath.resolve(varsResult.orThrow()))\n}\n\nexport const Path = {\n expand: expandPath,\n expandTilde,\n expandVars,\n join: (...segments: string[]): string => nodePath.join(...segments),\n resolve: (...segments: string[]): string => nodePath.resolve(...segments),\n dirname: (p: string): string => nodePath.dirname(p),\n basename: (p: string, suffix?: string): string => nodePath.basename(p, suffix),\n extname: (p: string): string => nodePath.extname(p),\n isAbsolute: (p: string): boolean => nodePath.isAbsolute(p),\n}\n"],"mappings":"iJAQA,MAAa,EAAe,GACtB,IAAM,IAAY,EAAG,SAAS,CAC9B,EAAE,WAAW,KAAK,EAAI,EAAE,WAAW,MAAM,CAAS,EAAS,KAAK,EAAG,SAAS,CAAE,EAAE,MAAM,EAAE,CAAC,CACtF,EAGI,EAAc,GAAyC,CAClE,IAAM,EAA2B,EAAE,CAC7B,EAAS,EAAE,QACf,6CACC,EAAQ,EAA4B,IAA6B,CAChE,IAAM,EAAU,GAAU,GAAQ,GAC5B,EAAQ,QAAQ,IAAI,GAK1B,OAJI,IAAU,IAAA,IACZ,EAAe,KAAK,EAAQ,CACrB,GAEF,GAEV,CAMD,OAJI,EAAe,OAAS,EACnB,EAAK,EAAU,EAAG,sBAAuB,yBAAyB,EAAe,KAAK,KAAK,GAAG,CAAC,CAGjG,EAAM,EAAO,EAGT,EAAc,GAAyC,CAElE,IAAM,EAAa,EADG,EAAY,EAAE,CACQ,CAE5C,OADI,EAAW,QAAQ,CAAS,EACzB,EAAM,EAAS,QAAQ,EAAW,SAAS,CAAC,CAAC,EAGzC,EAAO,CAClB,OAAQ,EACR,cACA,aACA,MAAO,GAAG,IAA+B,EAAS,KAAK,GAAG,EAAS,CACnE,SAAU,GAAG,IAA+B,EAAS,QAAQ,GAAG,EAAS,CACzE,QAAU,GAAsB,EAAS,QAAQ,EAAE,CACnD,UAAW,EAAW,IAA4B,EAAS,SAAS,EAAG,EAAO,CAC9E,QAAU,GAAsB,EAAS,QAAQ,EAAE,CACnD,WAAa,GAAuB,EAAS,WAAW,EAAE,CAC3D"}
1
+ {"version":3,"file":"PathExpander.js","names":[],"sources":["../../src/path/PathExpander.ts"],"sourcesContent":["import * as os from \"node:os\"\nimport * as nodePath from \"node:path\"\n\nimport type { Either } from \"functype\"\nimport { Left, Right } from \"functype\"\n\nimport { PathError } from \"../errors/errors\"\n\nexport const expandTilde = (p: string): string => {\n if (p === \"~\") return os.homedir()\n if (p.startsWith(\"~/\") || p.startsWith(\"~\\\\\")) return nodePath.join(os.homedir(), p.slice(2))\n return p\n}\n\nexport const expandVars = (p: string): Either<PathError, string> => {\n const unresolvedVars: string[] = []\n // Factor out the leading `$` and forbid `$` inside `${...}` so the engine\n // can't backtrack catastrophically on inputs like `${{${{${{...` (CodeQL\n // js/polynomial-redos).\n const result = p.replace(\n /\\$(?:\\{([^}$]+)\\}|([A-Za-z_][A-Za-z0-9_]*))/g,\n (_match, braced: string | undefined, bare: string | undefined) => {\n const varName = braced ?? bare ?? \"\"\n const value = process.env[varName]\n if (value === undefined) {\n unresolvedVars.push(varName)\n return _match\n }\n return value\n },\n )\n\n if (unresolvedVars.length > 0) {\n return Left(PathError(p, \"unresolved_variable\", `Unresolved variables: ${unresolvedVars.join(\", \")}`))\n }\n\n return Right(result)\n}\n\nexport const expandPath = (p: string): Either<PathError, string> => {\n const tildeExpanded = expandTilde(p)\n const varsResult = expandVars(tildeExpanded)\n if (varsResult.isLeft()) return varsResult\n return Right(nodePath.resolve(varsResult.orThrow()))\n}\n\nexport const Path = {\n expand: expandPath,\n expandTilde,\n expandVars,\n join: (...segments: string[]): string => nodePath.join(...segments),\n resolve: (...segments: string[]): string => nodePath.resolve(...segments),\n dirname: (p: string): string => nodePath.dirname(p),\n basename: (p: string, suffix?: string): string => nodePath.basename(p, suffix),\n extname: (p: string): string => nodePath.extname(p),\n isAbsolute: (p: string): boolean => nodePath.isAbsolute(p),\n}\n"],"mappings":"iJAQA,MAAa,EAAe,GACtB,IAAM,IAAY,EAAG,QAAQ,EAC7B,EAAE,WAAW,IAAI,GAAK,EAAE,WAAW,KAAK,EAAU,EAAS,KAAK,EAAG,QAAQ,EAAG,EAAE,MAAM,CAAC,CAAC,EACrF,EAGI,EAAc,GAAyC,CAClE,IAAM,EAA2B,CAAC,EAI5B,EAAS,EAAE,QACf,gDACC,EAAQ,EAA4B,IAA6B,CAChE,IAAM,EAAU,GAAU,GAAQ,GAC5B,EAAQ,QAAQ,IAAI,GAK1B,OAJI,IAAU,IAAA,IACZ,EAAe,KAAK,CAAO,EACpB,GAEF,CACT,CACF,EAMA,OAJI,EAAe,OAAS,EACnB,EAAK,EAAU,EAAG,sBAAuB,yBAAyB,EAAe,KAAK,IAAI,GAAG,CAAC,EAGhG,EAAM,CAAM,CACrB,EAEa,EAAc,GAAyC,CAElE,IAAM,EAAa,EADG,EAAY,CACQ,CAAC,EAE3C,OADI,EAAW,OAAO,EAAU,EACzB,EAAM,EAAS,QAAQ,EAAW,QAAQ,CAAC,CAAC,CACrD,EAEa,EAAO,CAClB,OAAQ,EACR,cACA,aACA,MAAO,GAAG,IAA+B,EAAS,KAAK,GAAG,CAAQ,EAClE,SAAU,GAAG,IAA+B,EAAS,QAAQ,GAAG,CAAQ,EACxE,QAAU,GAAsB,EAAS,QAAQ,CAAC,EAClD,UAAW,EAAW,IAA4B,EAAS,SAAS,EAAG,CAAM,EAC7E,QAAU,GAAsB,EAAS,QAAQ,CAAC,EAClD,WAAa,GAAuB,EAAS,WAAW,CAAC,CAC3D"}
@@ -1 +1 @@
1
- {"version":3,"file":"Platform.js","names":[],"sources":["../../src/platform/Platform.ts"],"sourcesContent":["import { execSync } from \"node:child_process\"\nimport * as fs from \"node:fs\"\nimport * as os from \"node:os\"\nimport * as path from \"node:path\"\n\nimport { List, Option } from \"functype\"\n\nexport type UserInfo = {\n readonly username: string\n readonly uid: number\n readonly gid: number\n readonly shell: string | null\n readonly homedir: string\n}\n\nexport type CloudProvider = \"onedrive\" | \"gdrive\" | \"dropbox\" | \"icloud\"\n\nexport type CloudStorageDir = {\n readonly provider: CloudProvider\n readonly path: string\n readonly label: string\n}\n\nconst hasDockerEnv = (): boolean => {\n try {\n fs.statSync(\"/.dockerenv\")\n return true\n } catch {\n return false\n }\n}\nconst hasDockerCGroup = (): boolean => {\n try {\n return fs.readFileSync(\"/proc/self/cgroup\", \"utf8\").includes(\"docker\")\n } catch {\n return false\n }\n}\n\nconst memo = <T>(fn: () => T): (() => T) => {\n const cache: { value?: T } = {}\n return () => {\n if (!(\"value\" in cache)) {\n cache.value = fn()\n }\n return cache.value as T\n }\n}\n\nconst cachedIsDocker = memo(() => hasDockerEnv() || hasDockerCGroup())\nconst cachedIsKube = memo(() => {\n try {\n return fs.readFileSync(\"/proc/self/cgroup\", \"utf8\").includes(\"kube\")\n } catch {\n return false\n }\n})\nconst cachedIsWSL = memo(() => {\n try {\n const version = fs.readFileSync(\"/proc/version\", \"utf8\")\n return version.includes(\"Microsoft\") || version.includes(\"WSL\")\n } catch {\n return false\n }\n})\nconst cachedIsCI = memo(\n () =>\n process.env[\"CI\"] !== undefined ||\n process.env[\"GITHUB_ACTIONS\"] !== undefined ||\n process.env[\"GITLAB_CI\"] !== undefined ||\n process.env[\"CIRCLECI\"] !== undefined ||\n process.env[\"JENKINS_URL\"] !== undefined ||\n process.env[\"TRAVIS\"] !== undefined ||\n process.env[\"BUILDKITE\"] !== undefined,\n)\n\nconst SYSTEM_ACCOUNTS = new Set([\"all users\", \"default\", \"default user\", \"public\"])\n\nconst isSystemAccount = (name: string): boolean => {\n const lower = name.toLowerCase()\n if (SYSTEM_ACCOUNTS.has(lower)) return true\n if (lower.startsWith(\"defaultuser\") || lower.startsWith(\"desktop.\") || lower.startsWith(\"wsiaccount\")) return true\n return false\n}\n\nconst isDirectory = (p: string): boolean => {\n try {\n return fs.statSync(p).isDirectory()\n } catch {\n return false\n }\n}\n\nconst readRealUsers = (usersDir: string): readonly string[] | undefined => {\n try {\n const entries = fs.readdirSync(usersDir)\n return entries.filter((name) => !isSystemAccount(name) && isDirectory(path.join(usersDir, name)))\n } catch {\n return undefined\n }\n}\n\nconst resolveViaCmdExe = (usersDir: string, fallback: string): Option<string> => {\n try {\n const raw = execSync(\"cmd.exe /c echo %USERPROFILE%\", { timeout: 3000, encoding: \"utf8\" }).trim()\n // Convert Windows path C:\\Users\\foo → /mnt/c/Users/foo\n const match = raw.match(/^([A-Za-z]):\\\\(.*)$/)\n if (match) {\n const drive = match[1].toLowerCase()\n const rest = match[2].replace(/\\\\/g, \"/\")\n const wslPath = `/mnt/${drive}/${rest}`\n if (isDirectory(wslPath)) {\n return Option(wslPath)\n }\n }\n } catch {\n // cmd.exe failed, fall through to best guess\n }\n return Option(fallback)\n}\n\nconst resolveWindowsHome = (): Option<string> => {\n if (!cachedIsWSL()) return Option<string>(undefined)\n\n const usersDir = \"/mnt/c/Users\"\n const realUsers = readRealUsers(usersDir)\n if (realUsers === undefined) return Option<string>(undefined)\n\n if (realUsers.length === 1) {\n return Option(path.join(usersDir, realUsers[0]))\n }\n\n if (realUsers.length > 1) {\n return resolveViaCmdExe(usersDir, path.join(usersDir, realUsers[0]))\n }\n\n return Option<string>(undefined)\n}\n\nconst cachedWindowsHome = memo(resolveWindowsHome)\n\nconst detectCloudProvider = (name: string): { provider: CloudProvider; label: string } | undefined => {\n if (name === \"OneDrive\" || name.startsWith(\"OneDrive \") || name.startsWith(\"OneDrive-\")) {\n return { provider: \"onedrive\", label: name }\n }\n if (name === \"Google Drive\") {\n return { provider: \"gdrive\", label: name }\n }\n if (name === \"Dropbox\") {\n return { provider: \"dropbox\", label: name }\n }\n return undefined\n}\n\nconst scanCloudStorageDirs = (home: string): CloudStorageDir[] => {\n const results: CloudStorageDir[] = []\n\n // Direct home children\n try {\n const entries = fs.readdirSync(home)\n for (const name of entries) {\n const fullPath = path.join(home, name)\n const detection = detectCloudProvider(name)\n if (detection && isDirectory(fullPath)) {\n results.push({ provider: detection.provider, path: fullPath, label: detection.label })\n }\n }\n } catch {\n // home dir may not exist or be readable\n }\n\n // macOS Library/CloudStorage children\n const cloudStoragePath = path.join(home, \"Library\", \"CloudStorage\")\n try {\n const entries = fs.readdirSync(cloudStoragePath)\n for (const name of entries) {\n const fullPath = path.join(cloudStoragePath, name)\n if (!isDirectory(fullPath)) continue\n if (name.startsWith(\"OneDrive\")) {\n results.push({ provider: \"onedrive\", path: fullPath, label: name })\n } else if (name.startsWith(\"GoogleDrive\")) {\n results.push({ provider: \"gdrive\", path: fullPath, label: name })\n }\n }\n } catch {\n // Library/CloudStorage may not exist\n }\n\n // macOS iCloud fixed path\n const icloudPath = path.join(home, \"Library\", \"Mobile Documents\", \"com~apple~CloudDocs\")\n if (isDirectory(icloudPath)) {\n results.push({ provider: \"icloud\", path: icloudPath, label: \"iCloud Drive\" })\n }\n\n return results\n}\n\nexport const Platform = {\n os: (): \"darwin\" | \"linux\" | \"win32\" | string => process.platform,\n arch: (): string => process.arch,\n homeDir: (): string => os.homedir(),\n tmpDir: (): string => os.tmpdir(),\n hostname: (): string => os.hostname(),\n eol: (): string => os.EOL,\n pathSep: (): string => path.sep,\n\n isWindows: (): boolean => process.platform === \"win32\",\n isMac: (): boolean => process.platform === \"darwin\",\n isLinux: (): boolean => process.platform === \"linux\",\n\n userInfo: (): Option<UserInfo> => {\n try {\n const info = os.userInfo()\n return Option({\n username: info.username,\n uid: info.uid,\n gid: info.gid,\n shell: info.shell,\n homedir: info.homedir,\n })\n } catch {\n return Option<UserInfo>(undefined)\n }\n },\n\n isDocker: (): boolean => cachedIsDocker(),\n isKubernetes: (): boolean => cachedIsKube(),\n isWSL: (): boolean => cachedIsWSL(),\n isCI: (): boolean => cachedIsCI(),\n\n isContainer: (): boolean => Platform.isDocker() || Platform.isKubernetes(),\n\n windowsHomeDir: (): Option<string> => cachedWindowsHome(),\n\n homeDirs: (): List<string> => {\n const homes: string[] = [os.homedir()]\n Platform.windowsHomeDir().forEach((winHome) => {\n if (winHome !== os.homedir()) {\n homes.push(winHome)\n }\n })\n return List(homes)\n },\n\n cloudStorageDirs: (home?: string): List<CloudStorageDir> => {\n if (home !== undefined) {\n return List(scanCloudStorageDirs(home))\n }\n const allDirs: CloudStorageDir[] = []\n const seenPaths = new Set<string>()\n Platform.homeDirs().forEach((h) => {\n for (const dir of scanCloudStorageDirs(h)) {\n if (!seenPaths.has(dir.path)) {\n seenPaths.add(dir.path)\n allDirs.push(dir)\n }\n }\n })\n return List(allDirs)\n },\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Platform.js","names":[],"sources":["../../src/platform/Platform.ts"],"sourcesContent":["import { execSync } from \"node:child_process\"\nimport * as fs from \"node:fs\"\nimport * as os from \"node:os\"\nimport * as path from \"node:path\"\n\nimport { List, Option } from \"functype\"\n\nexport type UserInfo = {\n readonly username: string\n readonly uid: number\n readonly gid: number\n readonly shell: string | null\n readonly homedir: string\n}\n\nexport type CloudProvider = \"onedrive\" | \"gdrive\" | \"dropbox\" | \"icloud\"\n\nexport type CloudStorageDir = {\n readonly provider: CloudProvider\n readonly path: string\n readonly label: string\n}\n\nconst hasDockerEnv = (): boolean => {\n try {\n fs.statSync(\"/.dockerenv\")\n return true\n } catch {\n return false\n }\n}\nconst hasDockerCGroup = (): boolean => {\n try {\n return fs.readFileSync(\"/proc/self/cgroup\", \"utf8\").includes(\"docker\")\n } catch {\n return false\n }\n}\n\nconst memo = <T>(fn: () => T): (() => T) => {\n const cache: { value?: T } = {}\n return () => {\n if (!(\"value\" in cache)) {\n cache.value = fn()\n }\n return cache.value as T\n }\n}\n\nconst cachedIsDocker = memo(() => hasDockerEnv() || hasDockerCGroup())\nconst cachedIsKube = memo(() => {\n try {\n return fs.readFileSync(\"/proc/self/cgroup\", \"utf8\").includes(\"kube\")\n } catch {\n return false\n }\n})\nconst cachedIsWSL = memo(() => {\n try {\n const version = fs.readFileSync(\"/proc/version\", \"utf8\")\n return version.includes(\"Microsoft\") || version.includes(\"WSL\")\n } catch {\n return false\n }\n})\nconst cachedIsCI = memo(\n () =>\n process.env[\"CI\"] !== undefined ||\n process.env[\"GITHUB_ACTIONS\"] !== undefined ||\n process.env[\"GITLAB_CI\"] !== undefined ||\n process.env[\"CIRCLECI\"] !== undefined ||\n process.env[\"JENKINS_URL\"] !== undefined ||\n process.env[\"TRAVIS\"] !== undefined ||\n process.env[\"BUILDKITE\"] !== undefined,\n)\n\nconst SYSTEM_ACCOUNTS = new Set([\"all users\", \"default\", \"default user\", \"public\"])\n\nconst isSystemAccount = (name: string): boolean => {\n const lower = name.toLowerCase()\n if (SYSTEM_ACCOUNTS.has(lower)) return true\n if (lower.startsWith(\"defaultuser\") || lower.startsWith(\"desktop.\") || lower.startsWith(\"wsiaccount\")) return true\n return false\n}\n\nconst isDirectory = (p: string): boolean => {\n try {\n return fs.statSync(p).isDirectory()\n } catch {\n return false\n }\n}\n\nconst readRealUsers = (usersDir: string): readonly string[] | undefined => {\n try {\n const entries = fs.readdirSync(usersDir)\n return entries.filter((name) => !isSystemAccount(name) && isDirectory(path.join(usersDir, name)))\n } catch {\n return undefined\n }\n}\n\nconst resolveViaCmdExe = (usersDir: string, fallback: string): Option<string> => {\n try {\n const raw = execSync(\"cmd.exe /c echo %USERPROFILE%\", { timeout: 3000, encoding: \"utf8\" }).trim()\n // Convert Windows path C:\\Users\\foo → /mnt/c/Users/foo\n const match = raw.match(/^([A-Za-z]):\\\\(.*)$/)\n if (match) {\n const drive = match[1].toLowerCase()\n const rest = match[2].replace(/\\\\/g, \"/\")\n const wslPath = `/mnt/${drive}/${rest}`\n if (isDirectory(wslPath)) {\n return Option(wslPath)\n }\n }\n } catch {\n // cmd.exe failed, fall through to best guess\n }\n return Option(fallback)\n}\n\nconst resolveWindowsHome = (): Option<string> => {\n if (!cachedIsWSL()) return Option<string>(undefined)\n\n const usersDir = \"/mnt/c/Users\"\n const realUsers = readRealUsers(usersDir)\n if (realUsers === undefined) return Option<string>(undefined)\n\n if (realUsers.length === 1) {\n return Option(path.join(usersDir, realUsers[0]))\n }\n\n if (realUsers.length > 1) {\n return resolveViaCmdExe(usersDir, path.join(usersDir, realUsers[0]))\n }\n\n return Option<string>(undefined)\n}\n\nconst cachedWindowsHome = memo(resolveWindowsHome)\n\nconst detectCloudProvider = (name: string): { provider: CloudProvider; label: string } | undefined => {\n if (name === \"OneDrive\" || name.startsWith(\"OneDrive \") || name.startsWith(\"OneDrive-\")) {\n return { provider: \"onedrive\", label: name }\n }\n if (name === \"Google Drive\") {\n return { provider: \"gdrive\", label: name }\n }\n if (name === \"Dropbox\") {\n return { provider: \"dropbox\", label: name }\n }\n return undefined\n}\n\nconst scanCloudStorageDirs = (home: string): CloudStorageDir[] => {\n const results: CloudStorageDir[] = []\n\n // Direct home children\n try {\n const entries = fs.readdirSync(home)\n for (const name of entries) {\n const fullPath = path.join(home, name)\n const detection = detectCloudProvider(name)\n if (detection && isDirectory(fullPath)) {\n results.push({ provider: detection.provider, path: fullPath, label: detection.label })\n }\n }\n } catch {\n // home dir may not exist or be readable\n }\n\n // macOS Library/CloudStorage children\n const cloudStoragePath = path.join(home, \"Library\", \"CloudStorage\")\n try {\n const entries = fs.readdirSync(cloudStoragePath)\n for (const name of entries) {\n const fullPath = path.join(cloudStoragePath, name)\n if (!isDirectory(fullPath)) continue\n if (name.startsWith(\"OneDrive\")) {\n results.push({ provider: \"onedrive\", path: fullPath, label: name })\n } else if (name.startsWith(\"GoogleDrive\")) {\n results.push({ provider: \"gdrive\", path: fullPath, label: name })\n }\n }\n } catch {\n // Library/CloudStorage may not exist\n }\n\n // macOS iCloud fixed path\n const icloudPath = path.join(home, \"Library\", \"Mobile Documents\", \"com~apple~CloudDocs\")\n if (isDirectory(icloudPath)) {\n results.push({ provider: \"icloud\", path: icloudPath, label: \"iCloud Drive\" })\n }\n\n return results\n}\n\nexport const Platform = {\n os: (): \"darwin\" | \"linux\" | \"win32\" | string => process.platform,\n arch: (): string => process.arch,\n homeDir: (): string => os.homedir(),\n tmpDir: (): string => os.tmpdir(),\n hostname: (): string => os.hostname(),\n eol: (): string => os.EOL,\n pathSep: (): string => path.sep,\n\n isWindows: (): boolean => process.platform === \"win32\",\n isMac: (): boolean => process.platform === \"darwin\",\n isLinux: (): boolean => process.platform === \"linux\",\n\n userInfo: (): Option<UserInfo> => {\n try {\n const info = os.userInfo()\n return Option({\n username: info.username,\n uid: info.uid,\n gid: info.gid,\n shell: info.shell,\n homedir: info.homedir,\n })\n } catch {\n return Option<UserInfo>(undefined)\n }\n },\n\n isDocker: (): boolean => cachedIsDocker(),\n isKubernetes: (): boolean => cachedIsKube(),\n isWSL: (): boolean => cachedIsWSL(),\n isCI: (): boolean => cachedIsCI(),\n\n isContainer: (): boolean => Platform.isDocker() || Platform.isKubernetes(),\n\n windowsHomeDir: (): Option<string> => cachedWindowsHome(),\n\n homeDirs: (): List<string> => {\n const homes: string[] = [os.homedir()]\n Platform.windowsHomeDir().forEach((winHome) => {\n if (winHome !== os.homedir()) {\n homes.push(winHome)\n }\n })\n return List(homes)\n },\n\n cloudStorageDirs: (home?: string): List<CloudStorageDir> => {\n if (home !== undefined) {\n return List(scanCloudStorageDirs(home))\n }\n const allDirs: CloudStorageDir[] = []\n const seenPaths = new Set<string>()\n Platform.homeDirs().forEach((h) => {\n for (const dir of scanCloudStorageDirs(h)) {\n if (!seenPaths.has(dir.path)) {\n seenPaths.add(dir.path)\n allDirs.push(dir)\n }\n }\n })\n return List(allDirs)\n },\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Process.js","names":["nodeExecSync"],"sources":["../../src/process/Process.ts"],"sourcesContent":["import { exec as execCb, execSync as nodeExecSync } from \"node:child_process\"\n\nimport type { Either, TaskResult } from \"functype\"\nimport { Err, Left, Ok, Right } from \"functype\"\n\nimport { ProcessError } from \"../errors/errors\"\n\nexport type ExecResult = {\n readonly stdout: string\n readonly stderr: string\n readonly exitCode: number\n}\n\nexport const Process = {\n exec: (command: string, options?: { timeout?: number; cwd?: string }): TaskResult<ExecResult> => {\n return new Promise((resolve) => {\n execCb(command, { timeout: options?.timeout, cwd: options?.cwd }, (error, stdout, stderr) => {\n if (error) {\n // exec callback error has `code` as exit code (number) — distinct from Node errno `code` (string)\n const exitCode = typeof error.code === \"number\" ? error.code : null\n resolve(Err(ProcessError(command, exitCode, String(stderr))))\n } else {\n resolve(Ok({ stdout: String(stdout), stderr: String(stderr), exitCode: 0 }))\n }\n })\n })\n },\n\n execSync: (command: string, options?: { timeout?: number; cwd?: string }): Either<ProcessError, ExecResult> => {\n try {\n const stdout = nodeExecSync(command, {\n timeout: options?.timeout,\n cwd: options?.cwd,\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n })\n return Right({ stdout: String(stdout), stderr: \"\", exitCode: 0 })\n } catch (error) {\n if (error instanceof Error && \"status\" in error && \"stderr\" in error) {\n const execError = error as Error & { status: number; stderr: string }\n return Left(ProcessError(command, execError.status, String(execError.stderr)))\n }\n return Left(ProcessError(command, null, \"\", error instanceof Error ? error.message : String(error)))\n }\n },\n}\n"],"mappings":"uKAaA,MAAa,EAAU,CACrB,MAAO,EAAiB,IACf,IAAI,QAAS,GAAY,CAC9B,EAAO,EAAS,CAAE,QAAS,GAAS,QAAS,IAAK,GAAS,IAAK,EAAG,EAAO,EAAQ,IAAW,CAIzF,EAHE,EAGM,EAAI,EAAa,EADR,OAAO,EAAM,MAAS,SAAW,EAAM,KAAO,KACnB,OAAO,EAAO,CAAC,CAAC,CAEpD,EAAG,CAAE,OAAQ,OAAO,EAAO,CAAE,OAAQ,OAAO,EAAO,CAAE,SAAU,EAAG,CAAC,CAAC,EAE9E,EACF,CAGJ,UAAW,EAAiB,IAAmF,CAC7G,GAAI,CACF,IAAM,EAASA,EAAa,EAAS,CACnC,QAAS,GAAS,QAClB,IAAK,GAAS,IACd,SAAU,OACV,MAAO,CAAC,OAAQ,OAAQ,OAAO,CAChC,CAAC,CACF,OAAO,EAAM,CAAE,OAAQ,OAAO,EAAO,CAAE,OAAQ,GAAI,SAAU,EAAG,CAAC,OAC1D,EAAO,CACd,GAAI,aAAiB,OAAS,WAAY,GAAS,WAAY,EAAO,CACpE,IAAM,EAAY,EAClB,OAAO,EAAK,EAAa,EAAS,EAAU,OAAQ,OAAO,EAAU,OAAO,CAAC,CAAC,CAEhF,OAAO,EAAK,EAAa,EAAS,KAAM,GAAI,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAC,CAAC,GAGzG"}
1
+ {"version":3,"file":"Process.js","names":["nodeExecSync"],"sources":["../../src/process/Process.ts"],"sourcesContent":["import { exec as execCb, execSync as nodeExecSync } from \"node:child_process\"\n\nimport type { Either, TaskResult } from \"functype\"\nimport { Err, Left, Ok, Right } from \"functype\"\n\nimport { ProcessError } from \"../errors/errors\"\n\nexport type ExecResult = {\n readonly stdout: string\n readonly stderr: string\n readonly exitCode: number\n}\n\nexport const Process = {\n exec: (command: string, options?: { timeout?: number; cwd?: string }): TaskResult<ExecResult> => {\n return new Promise((resolve) => {\n execCb(command, { timeout: options?.timeout, cwd: options?.cwd }, (error, stdout, stderr) => {\n if (error) {\n // exec callback error has `code` as exit code (number) — distinct from Node errno `code` (string)\n const exitCode = typeof error.code === \"number\" ? error.code : null\n resolve(Err(ProcessError(command, exitCode, String(stderr))))\n } else {\n resolve(Ok({ stdout: String(stdout), stderr: String(stderr), exitCode: 0 }))\n }\n })\n })\n },\n\n execSync: (command: string, options?: { timeout?: number; cwd?: string }): Either<ProcessError, ExecResult> => {\n try {\n const stdout = nodeExecSync(command, {\n timeout: options?.timeout,\n cwd: options?.cwd,\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n })\n return Right({ stdout: String(stdout), stderr: \"\", exitCode: 0 })\n } catch (error) {\n if (error instanceof Error && \"status\" in error && \"stderr\" in error) {\n const execError = error as Error & { status: number; stderr: string }\n return Left(ProcessError(command, execError.status, String(execError.stderr)))\n }\n return Left(ProcessError(command, null, \"\", error instanceof Error ? error.message : String(error)))\n }\n },\n}\n"],"mappings":"uKAaA,MAAa,EAAU,CACrB,MAAO,EAAiB,IACf,IAAI,QAAS,GAAY,CAC9B,EAAO,EAAS,CAAE,QAAS,GAAS,QAAS,IAAK,GAAS,GAAI,GAAI,EAAO,EAAQ,IAAW,CAIzF,EAHE,EAGM,EAAI,EAAa,EADR,OAAO,EAAM,MAAS,SAAW,EAAM,KAAO,KACnB,OAAO,CAAM,CAAC,CAAC,EAEnD,EAAG,CAAE,OAAQ,OAAO,CAAM,EAAG,OAAQ,OAAO,CAAM,EAAG,SAAU,CAAE,CAAC,CAAC,CAE/E,CAAC,CACH,CAAC,EAGH,UAAW,EAAiB,IAAmF,CAC7G,GAAI,CACF,IAAM,EAASA,EAAa,EAAS,CACnC,QAAS,GAAS,QAClB,IAAK,GAAS,IACd,SAAU,OACV,MAAO,CAAC,OAAQ,OAAQ,MAAM,CAChC,CAAC,EACD,OAAO,EAAM,CAAE,OAAQ,OAAO,CAAM,EAAG,OAAQ,GAAI,SAAU,CAAE,CAAC,CAClE,OAAS,EAAO,CACd,GAAI,aAAiB,OAAS,WAAY,GAAS,WAAY,EAAO,CACpE,IAAM,EAAY,EAClB,OAAO,EAAK,EAAa,EAAS,EAAU,OAAQ,OAAO,EAAU,MAAM,CAAC,CAAC,CAC/E,CACA,OAAO,EAAK,EAAa,EAAS,KAAM,GAAI,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAAC,CAAC,CACrG,CACF,CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functype-os",
3
- "version": "0.60.0",
3
+ "version": "0.60.6",
4
4
  "description": "Functional OS utilities using functype data structures — env vars, path expansion, file ops, platform detection",
5
5
  "keywords": [
6
6
  "functype",
@@ -13,35 +13,22 @@
13
13
  ],
14
14
  "author": "jordan.burke@gmail.com",
15
15
  "license": "MIT",
16
- "homepage": "https://github.com/jordanburke/functype-os",
16
+ "homepage": "https://github.com/jordanburke/functype/tree/main/packages/functype-os",
17
17
  "repository": {
18
18
  "type": "git",
19
- "url": "https://github.com/jordanburke/functype-os"
20
- },
21
- "scripts": {
22
- "validate": "ts-builds validate",
23
- "format": "ts-builds format",
24
- "format:check": "ts-builds format:check",
25
- "lint": "ts-builds lint",
26
- "lint:check": "ts-builds lint:check",
27
- "typecheck": "ts-builds typecheck",
28
- "test": "ts-builds test",
29
- "test:watch": "ts-builds test:watch",
30
- "test:coverage": "ts-builds test:coverage",
31
- "build": "ts-builds build",
32
- "dev": "ts-builds dev",
33
- "prepublishOnly": "pnpm validate"
19
+ "url": "https://github.com/jordanburke/functype",
20
+ "directory": "packages/functype-os"
34
21
  },
35
22
  "peerDependencies": {
36
- "functype": ">=0.54.0"
23
+ "functype": "^0.60.6"
37
24
  },
38
25
  "devDependencies": {
39
- "@types/node": "^24.12.2",
26
+ "@types/node": "^24.12.4",
40
27
  "eslint-config-prettier": "^10.1.8",
41
- "functype": "^0.60.0",
42
- "ts-builds": "^2.7.0",
43
- "tsdown": "^0.21.9",
44
- "vitest": "^4.1.4"
28
+ "ts-builds": "^2.8.0",
29
+ "tsdown": "^0.22.0",
30
+ "vitest": "^4.1.6",
31
+ "functype": "^0.60.6"
45
32
  },
46
33
  "type": "module",
47
34
  "main": "./dist/index.js",
@@ -94,8 +81,24 @@
94
81
  "dist"
95
82
  ],
96
83
  "prettier": "ts-builds/prettier",
97
- "packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319",
98
84
  "engines": {
99
85
  "node": ">=18.17.0"
86
+ },
87
+ "publishConfig": {
88
+ "access": "public",
89
+ "provenance": true
90
+ },
91
+ "scripts": {
92
+ "validate": "ts-builds validate",
93
+ "format": "ts-builds format",
94
+ "format:check": "ts-builds format:check",
95
+ "lint": "ts-builds lint",
96
+ "lint:check": "ts-builds lint:check",
97
+ "typecheck": "ts-builds typecheck",
98
+ "test": "ts-builds test",
99
+ "test:watch": "ts-builds test:watch",
100
+ "test:coverage": "ts-builds test:coverage",
101
+ "build": "ts-builds build",
102
+ "dev": "ts-builds dev"
100
103
  }
101
- }
104
+ }