functype-os 1.3.1 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ConfigResolver-CovnoBgc.d.ts → ConfigResolver-C2SPGvWO.d.ts} +2 -2
- package/dist/{Env-CSZ1G2G-.d.ts → Env-BGw_5lWx.d.ts} +2 -2
- package/dist/{Fs-CAAIRZMK.d.ts → Fs-Be3S3EHP.d.ts} +3 -3
- package/dist/{PathExpander-DztbeAeQ.d.ts → PathExpander-CjiEMvqX.d.ts} +2 -2
- package/dist/{Platform-ClVroRSa.d.ts → Platform-DotricJv.d.ts} +2 -2
- package/dist/{Process-B522T3x3.d.ts → Process-WxEgO5iR.d.ts} +2 -2
- package/dist/config/ConfigResolver.d.ts +1 -1
- package/dist/config/ConfigResolver.js +1 -1
- package/dist/config/ConfigResolver.js.map +1 -1
- package/dist/config/bootDiagnostics.js +1 -1
- package/dist/config/bootDiagnostics.js.map +1 -1
- package/dist/config/colors.js +1 -1
- package/dist/config/colors.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/env/Env.d.ts +1 -1
- package/dist/env/Env.js +1 -1
- package/dist/env/Env.js.map +1 -1
- package/dist/env/index.d.ts +1 -1
- package/dist/errors/errors.d.ts +1 -1
- package/dist/errors/errors.js +1 -1
- package/dist/errors/errors.js.map +1 -1
- package/dist/errors/index.d.ts +1 -1
- package/dist/{errors-CdjTx2HM.d.ts → errors-C6fjQdSc.d.ts} +5 -3
- package/dist/fs/Fs.d.ts +1 -1
- package/dist/fs/Fs.js +1 -1
- package/dist/fs/Fs.js.map +1 -1
- package/dist/fs/index.d.ts +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/path/PathExpander.d.ts +1 -1
- package/dist/path/PathExpander.js +1 -1
- package/dist/path/PathExpander.js.map +1 -1
- package/dist/path/index.d.ts +1 -1
- package/dist/platform/Platform.d.ts +1 -1
- package/dist/platform/Platform.js +1 -1
- package/dist/platform/Platform.js.map +1 -1
- package/dist/platform/index.d.ts +1 -1
- package/dist/process/Process.d.ts +1 -1
- package/dist/process/Process.js +1 -1
- package/dist/process/Process.js.map +1 -1
- package/dist/process/index.d.ts +1 -1
- package/package.json +6 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ConfigError } from "./errors-
|
|
1
|
+
import { t as ConfigError } from "./errors-C6fjQdSc.js";
|
|
2
2
|
import { Either, List, Option, TaskResult } from "functype";
|
|
3
3
|
|
|
4
4
|
//#region src/config/ConfigResolver.d.ts
|
|
@@ -24,4 +24,4 @@ declare const ConfigResolver: {
|
|
|
24
24
|
};
|
|
25
25
|
//#endregion
|
|
26
26
|
export { ConfigResolver as t };
|
|
27
|
-
//# sourceMappingURL=ConfigResolver-
|
|
27
|
+
//# sourceMappingURL=ConfigResolver-C2SPGvWO.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as EnvError } from "./errors-
|
|
1
|
+
import { n as EnvError } from "./errors-C6fjQdSc.js";
|
|
2
2
|
import { Either, List, Option } from "functype";
|
|
3
3
|
|
|
4
4
|
//#region src/env/Env.d.ts
|
|
@@ -14,4 +14,4 @@ declare const EnvCompanion: {
|
|
|
14
14
|
declare const Env: typeof EnvConstructor & typeof EnvCompanion;
|
|
15
15
|
//#endregion
|
|
16
16
|
export { Env as t };
|
|
17
|
-
//# sourceMappingURL=Env-
|
|
17
|
+
//# sourceMappingURL=Env-BGw_5lWx.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as FsError } from "./errors-
|
|
1
|
+
import { r as FsError } from "./errors-C6fjQdSc.js";
|
|
2
2
|
import { Either, List, Option, TaskResult } from "functype";
|
|
3
3
|
|
|
4
4
|
//#region src/fs/Fs.d.ts
|
|
@@ -26,6 +26,7 @@ declare const Fs: {
|
|
|
26
26
|
mkdir: (p: string, options?: {
|
|
27
27
|
recursive?: boolean;
|
|
28
28
|
}) => TaskResult<void>;
|
|
29
|
+
unlink: (p: string) => TaskResult<void>;
|
|
29
30
|
existsSync: (p: string) => boolean;
|
|
30
31
|
readFileSync: (p: string, encoding?: BufferEncoding) => Either<FsError, string>;
|
|
31
32
|
readFileOptSync: (p: string, encoding?: BufferEncoding) => Either<FsError, Option<string>>;
|
|
@@ -38,9 +39,8 @@ declare const Fs: {
|
|
|
38
39
|
mkdirSync: (p: string, options?: {
|
|
39
40
|
recursive?: boolean;
|
|
40
41
|
}) => Either<FsError, void>;
|
|
41
|
-
unlink: (p: string) => TaskResult<void>;
|
|
42
42
|
unlinkSync: (p: string) => Either<FsError, void>;
|
|
43
43
|
};
|
|
44
44
|
//#endregion
|
|
45
45
|
export { Fs as n, FileInfo as t };
|
|
46
|
-
//# sourceMappingURL=Fs-
|
|
46
|
+
//# sourceMappingURL=Fs-Be3S3EHP.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as PathError } from "./errors-
|
|
1
|
+
import { a as PathError } from "./errors-C6fjQdSc.js";
|
|
2
2
|
import { Either } from "functype";
|
|
3
3
|
|
|
4
4
|
//#region src/path/PathExpander.d.ts
|
|
@@ -18,4 +18,4 @@ declare const Path: {
|
|
|
18
18
|
};
|
|
19
19
|
//#endregion
|
|
20
20
|
export { expandVars as i, expandPath as n, expandTilde as r, Path as t };
|
|
21
|
-
//# sourceMappingURL=PathExpander-
|
|
21
|
+
//# sourceMappingURL=PathExpander-CjiEMvqX.d.ts.map
|
|
@@ -5,7 +5,7 @@ type UserInfo = {
|
|
|
5
5
|
readonly username: string;
|
|
6
6
|
readonly uid: number;
|
|
7
7
|
readonly gid: number;
|
|
8
|
-
readonly shell: string
|
|
8
|
+
readonly shell: Option<string>;
|
|
9
9
|
readonly homedir: string;
|
|
10
10
|
};
|
|
11
11
|
type CloudProvider = "onedrive" | "gdrive" | "dropbox" | "icloud";
|
|
@@ -37,4 +37,4 @@ declare const Platform: {
|
|
|
37
37
|
};
|
|
38
38
|
//#endregion
|
|
39
39
|
export { UserInfo as i, CloudStorageDir as n, Platform as r, CloudProvider as t };
|
|
40
|
-
//# sourceMappingURL=Platform-
|
|
40
|
+
//# sourceMappingURL=Platform-DotricJv.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { o as ProcessError } from "./errors-
|
|
1
|
+
import { o as ProcessError } from "./errors-C6fjQdSc.js";
|
|
2
2
|
import { Either, TaskResult } from "functype";
|
|
3
3
|
|
|
4
4
|
//#region src/process/Process.d.ts
|
|
@@ -19,4 +19,4 @@ declare const Process: {
|
|
|
19
19
|
};
|
|
20
20
|
//#endregion
|
|
21
21
|
export { Process as n, ExecResult as t };
|
|
22
|
-
//# sourceMappingURL=Process-
|
|
22
|
+
//# sourceMappingURL=Process-WxEgO5iR.d.ts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as ConfigResolver } from "../ConfigResolver-
|
|
1
|
+
import { t as ConfigResolver } from "../ConfigResolver-C2SPGvWO.js";
|
|
2
2
|
export { ConfigResolver };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ConfigError as e}from"../errors/errors.js";import{Fs as t}from"../fs/Fs.js";import{expandPath as n}from"../path/PathExpander.js";import{Err as r,Left as i,List as a,Ok as o,Option as s,Right as c}from"functype";const l=e=>n(e).fold(()=>s(void 0),e=>s(e)),u=
|
|
1
|
+
import{ConfigError as e}from"../errors/errors.js";import{Fs as t}from"../fs/Fs.js";import{expandPath as n}from"../path/PathExpander.js";import{Err as r,Left as i,List as a,Ok as o,Option as s,Right as c}from"functype";const l=e=>n(e).fold(()=>s(void 0),e=>s(e)),u=async(e,n)=>{if(n>=e.length)return s(void 0);let r=e[n],i=l(r);if(i.isNone())return u(e,n+1);let a=await t.exists(i.orThrow());return a.isOk()&&a.value?i:u(e,n+1)},d=e=>a(e.flatMap(e=>l(e).toArray())),f={resolve:async e=>o(await u(e.candidates,0)),resolveRequired:async t=>{let n=await f.resolve(t);return n.isErr()?r(n.error):n.orThrow().fold(()=>Promise.resolve(r(e(t.candidates))),e=>Promise.resolve(o(e)))},resolveAll:async e=>{let n=d(e.candidates).toArray();return o(a((await Promise.all(n.map(async e=>{let n=await t.exists(e);return n.isOk()&&n.value?e:null}))).filter(e=>e!==null)))},resolveSync:e=>d(e.candidates).find(t.existsSync),resolveRequiredSync:t=>f.resolveSync(t).fold(()=>i(e(t.candidates)),e=>c(e)),resolveAllSync:e=>d(e.candidates).filter(t.existsSync)};export{f as ConfigResolver};
|
|
2
2
|
//# sourceMappingURL=ConfigResolver.js.map
|
|
@@ -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\
|
|
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\nconst findFirstExistingAsync = async (candidates: readonly string[], startIndex: number): Promise<Option<string>> => {\n if (startIndex >= candidates.length) return Option<string>(undefined)\n const candidate = candidates[startIndex] as string\n const expanded = tryExpandPath(candidate)\n if (expanded.isNone()) return findFirstExistingAsync(candidates, startIndex + 1)\n const existsResult = await Fs.exists(expanded.orThrow())\n if (existsResult.isOk() && existsResult.value) return expanded\n return findFirstExistingAsync(candidates, startIndex + 1)\n}\n\n// Expand each candidate; drop entries whose env variables didn't resolve.\nconst presentPaths = (candidates: readonly string[]): List<string> =>\n List<string>(candidates.flatMap((c) => tryExpandPath(c).toArray() as string[]))\n\nexport const ConfigResolver = {\n // Async methods — return TaskResult<T>\n\n resolve: async (options: { readonly candidates: readonly string[] }): TaskResult<Option<string>> => {\n const found = await findFirstExistingAsync(options.candidates, 0)\n return Ok(found)\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 return result.orThrow().fold<TaskResult<string>>(\n () => Promise.resolve(Err(ConfigErrorConstructor(options.candidates))),\n (v) => Promise.resolve(Ok(v)),\n )\n },\n\n resolveAll: async (options: { readonly candidates: readonly string[] }): TaskResult<List<string>> => {\n const expanded = presentPaths(options.candidates).toArray()\n const checks = await Promise.all(\n expanded.map(async (p): Promise<string | null> => {\n const r = await Fs.exists(p)\n return r.isOk() && r.value ? p : null\n }),\n )\n const found = checks.filter((p): p is string => p !== null)\n return Ok(List<string>(found))\n },\n\n // Sync methods — return Either<ConfigError, T>\n\n resolveSync: (options: { readonly candidates: readonly string[] }): Option<string> =>\n presentPaths(options.candidates).find(Fs.existsSync),\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 presentPaths(options.candidates).filter(Fs.existsSync),\n}\n"],"mappings":"0NAQA,MAAM,EAAiB,GACN,EAAW,CACd,CAAC,CAAC,SACN,EAAe,IAAA,EAAS,EAC7B,GAAM,EAAO,CAAC,CACjB,EAGI,EAAyB,MAAO,EAA+B,IAAgD,CACnH,GAAI,GAAc,EAAW,OAAQ,OAAO,EAAe,IAAA,EAAS,EACpE,IAAM,EAAY,EAAW,GACvB,EAAW,EAAc,CAAS,EACxC,GAAI,EAAS,OAAO,EAAG,OAAO,EAAuB,EAAY,EAAa,CAAC,EAC/E,IAAM,EAAe,MAAM,EAAG,OAAO,EAAS,QAAQ,CAAC,EAEvD,OADI,EAAa,KAAK,GAAK,EAAa,MAAc,EAC/C,EAAuB,EAAY,EAAa,CAAC,CAC1D,EAGM,EAAgB,GACpB,EAAa,EAAW,QAAS,GAAM,EAAc,CAAC,CAAC,CAAC,QAAQ,CAAa,CAAC,EAEnE,EAAiB,CAG5B,QAAS,KAAO,IAEP,EAAG,MADU,EAAuB,EAAQ,WAAY,CAAC,CACjD,EAGjB,gBAAiB,KAAO,IAA4E,CAClG,IAAM,EAAS,MAAM,EAAe,QAAQ,CAAO,EAGnD,OAFI,EAAO,MAAM,EAAU,EAAI,EAAO,KAAK,EAEpC,EAAO,QAAQ,CAAC,CAAC,SAChB,QAAQ,QAAQ,EAAIA,EAAuB,EAAQ,UAAU,CAAC,CAAC,EACpE,GAAM,QAAQ,QAAQ,EAAG,CAAC,CAAC,CAC9B,CACF,EAEA,WAAY,KAAO,IAAkF,CACnG,IAAM,EAAW,EAAa,EAAQ,UAAU,CAAC,CAAC,QAAQ,EAQ1D,OAAO,EAAG,GADI,MANO,QAAQ,IAC3B,EAAS,IAAI,KAAO,IAA8B,CAChD,IAAM,EAAI,MAAM,EAAG,OAAO,CAAC,EAC3B,OAAO,EAAE,KAAK,GAAK,EAAE,MAAQ,EAAI,IACnC,CAAC,CACH,EAAA,CACqB,OAAQ,GAAmB,IAAM,IAC3B,CAAC,CAAC,CAC/B,EAIA,YAAc,GACZ,EAAa,EAAQ,UAAU,CAAC,CAAC,KAAK,EAAG,UAAU,EAErD,oBAAsB,GACL,EAAe,YAAY,CAC9B,CAAC,CAAC,SACN,EAAKA,EAAuB,EAAQ,UAAU,CAAC,EACpD,GAAM,EAAM,CAAC,CAChB,EAGF,eAAiB,GACf,EAAa,EAAQ,UAAU,CAAC,CAAC,OAAO,EAAG,UAAU,CACzD"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{blue as e,green as t,magenta as n,red as r,yellow as i}from"./colors.js";import{consoleBootLogger as a}from"./consoleBootLogger.js";import{maskValue as o}from"./mask.js";import{Left as s,List as c,Right as l}from"functype";const u=u=>{let d=u.logger??a,f=u.required??[],p=u.sensitive??[],m=u.public??[];d.info(`${e(`📦`)} Boot diagnostics: ${u.serviceName??`service`}`),d.info(` source: ${u.source.name}`);let h=f.filter(e=>u.source.get(e).isEmpty);if(p.length>0
|
|
1
|
+
import{blue as e,green as t,magenta as n,red as r,yellow as i}from"./colors.js";import{consoleBootLogger as a}from"./consoleBootLogger.js";import{maskValue as o}from"./mask.js";import{Left as s,List as c,Right as l}from"functype";const u=u=>{let d=u.logger??a,f=u.required??[],p=u.sensitive??[],m=u.public??[];d.info(`${e(`📦`)} Boot diagnostics: ${u.serviceName??`service`}`),d.info(` source: ${u.source.name}`);let h=f.filter(e=>u.source.get(e).isEmpty);if(p.length>0&&(d.info(i(`🔐 Sensitive:`)),p.forEach(e=>{let t=u.source.get(e).fold(()=>r(`NOT_LOADED`),e=>o(e));d.info(` ${e.padEnd(28)} ${t}`)})),m.length>0&&(d.info(t(`⚙️ Public:`)),m.forEach(e=>{let t=u.source.get(e).fold(()=>r(`NOT_LOADED`),e=>e);d.info(` ${e.padEnd(28)} ${t}`)})),u.hostEnv!==void 0&&u.vaultEnvKey!==void 0){let e=u.source.get(u.vaultEnvKey),{hostEnv:r}=u,{vaultEnvKey:i}=u;e.fold(()=>{d.warn(`Vault env key '${i}' not present — skipping mismatch check`)},e=>{e===r?d.info(`${n(`🌍`)} Environment: ${r} (host) ↔ ${e} (vault) ${t(`✓`)}`):d.error(`${n(`🌍`)} Environment MISMATCH: host=${r} vault=${e}`,{hostEnv:r,vaultEnv:e})})}if(h.length===0)return d.info(t(`✅ All required keys present`)),l(void 0);d.error(r(`❌ Missing required keys (${h.length}):`)),h.forEach(e=>d.error(` ${e}`));let g=c(h.map(e=>({key:e,required:!0})));return u.failOn===`missing`&&process.exit(1),s(g)};export{u as bootDiagnostics};
|
|
2
2
|
//# sourceMappingURL=bootDiagnostics.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootDiagnostics.js","names":[],"sources":["../../src/config/bootDiagnostics.ts"],"sourcesContent":["import type { Either, List as ListType } from \"functype\"\nimport { Left, List, Right } from \"functype\"\n// Logger is type-only and subpath-only in 1.3.x (rolldown chunk-splitter\n// workaround — see comment in packages/functype/src/index.ts). Restore to\n// `import type { ..., Logger } from \"functype\"` when rolldown is fixed.\nimport type { Logger } from \"functype/logger\"\n\nimport { blue, green, magenta, red, yellow } from \"./colors\"\nimport type { ConfigSource } from \"./ConfigSource\"\nimport { consoleBootLogger } from \"./consoleBootLogger\"\nimport { maskValue } from \"./mask\"\n\nexport interface MissingKey {\n readonly key: string\n readonly required: boolean\n}\n\nexport interface BootDiagnosticsOptions {\n /** The composed `ConfigSource` to inspect. */\n readonly source: ConfigSource\n /** Keys that MUST be present. Missing required keys produce a `Left`. */\n readonly required?: readonly string[]\n /** Keys to log with masked values (via {@link maskValue}). */\n readonly sensitive?: readonly string[]\n /** Keys to log with raw values. */\n readonly public?: readonly string[]\n /**\n * If provided with `vaultEnvKey`, compares the host environment string\n * (e.g. `process.env.NODE_ENV`) against the value at `vaultEnvKey` in the\n * source. Logs `✓` on match, an error-level message on mismatch.\n */\n readonly hostEnv?: string\n readonly vaultEnvKey?: string\n /**\n * `\"missing\"` triggers `process.exit(1)` after logging when any required key\n * is missing. `\"never\"` (default) returns `Left(missing)` and lets the caller\n * decide. Set to `\"missing\"` in production / staging boot paths to guarantee\n * fail-fast on misconfiguration.\n */\n readonly failOn?: \"missing\" | \"never\"\n /**\n * Logger to use. Defaults to {@link consoleBootLogger}. Any value satisfying\n * the core `Logger` interface from `functype` — including `DirectLogger`\n * from `functype-log/direct` — works without an adapter.\n */\n readonly logger?: Logger\n /** Service identifier shown in the diagnostics header. */\n readonly serviceName?: string\n}\n\n/**\n * Log a standardized boot diagnostics block and verify required-key presence.\n *\n * The block always emits, regardless of outcome — operational visibility (\"did\n * the deploy pick up my config?\") is the point. Sensitive keys are masked;\n * public keys are logged verbatim. An optional host-vs-vault env-mismatch\n * check catches the common deploy footgun where the host's `NODE_ENV` and the\n * vault's `ENV` (or equivalent) diverge.\n *\n * Returns `Either<List<MissingKey>, void>` so non-fatal callers can inspect\n * the result. Setting `failOn: \"missing\"` short-circuits to `process.exit(1)`\n * for production guards.\n *\n * @example\n * ```ts\n * const result = bootDiagnostics({\n * serviceName: \"cq-api\",\n * source: Layered([ProcessEnvSource(), await InfisicalSource(...)]),\n * required: [\"SUPABASE_URL\", \"SUPABASE_KEY\", \"OPENAI_API_KEY\"],\n * sensitive: [\"SUPABASE_URL\", \"SUPABASE_KEY\", \"OPENAI_API_KEY\"],\n * public: [\"ENV\", \"ENABLE_CHAT\"],\n * hostEnv: process.env.NODE_ENV ?? \"local\",\n * vaultEnvKey: \"ENV\",\n * failOn: process.env.NODE_ENV === \"production\" ? \"missing\" : \"never\",\n * })\n * ```\n */\nexport const bootDiagnostics = (opts: BootDiagnosticsOptions): Either<ListType<MissingKey>, void> => {\n const logger = opts.logger ?? consoleBootLogger\n const required = opts.required ?? []\n const sensitive = opts.sensitive ?? []\n const publicKeys = opts.public ?? []\n\n logger.info(`${blue(\"📦\")} Boot diagnostics: ${opts.serviceName ?? \"service\"}`)\n logger.info(` source: ${opts.source.name}`)\n\n const missing = required.filter((k) => opts.source.get(k).isEmpty)\n\n if (sensitive.length > 0) {\n logger.info(yellow(\"🔐 Sensitive:\"))\n
|
|
1
|
+
{"version":3,"file":"bootDiagnostics.js","names":[],"sources":["../../src/config/bootDiagnostics.ts"],"sourcesContent":["import type { Either, List as ListType } from \"functype\"\nimport { Left, List, Right } from \"functype\"\n// Logger is type-only and subpath-only in 1.3.x (rolldown chunk-splitter\n// workaround — see comment in packages/functype/src/index.ts). Restore to\n// `import type { ..., Logger } from \"functype\"` when rolldown is fixed.\nimport type { Logger } from \"functype/logger\"\n\nimport { blue, green, magenta, red, yellow } from \"./colors\"\nimport type { ConfigSource } from \"./ConfigSource\"\nimport { consoleBootLogger } from \"./consoleBootLogger\"\nimport { maskValue } from \"./mask\"\n\nexport interface MissingKey {\n readonly key: string\n readonly required: boolean\n}\n\nexport interface BootDiagnosticsOptions {\n /** The composed `ConfigSource` to inspect. */\n readonly source: ConfigSource\n /** Keys that MUST be present. Missing required keys produce a `Left`. */\n readonly required?: readonly string[]\n /** Keys to log with masked values (via {@link maskValue}). */\n readonly sensitive?: readonly string[]\n /** Keys to log with raw values. */\n readonly public?: readonly string[]\n /**\n * If provided with `vaultEnvKey`, compares the host environment string\n * (e.g. `process.env.NODE_ENV`) against the value at `vaultEnvKey` in the\n * source. Logs `✓` on match, an error-level message on mismatch.\n */\n readonly hostEnv?: string\n readonly vaultEnvKey?: string\n /**\n * `\"missing\"` triggers `process.exit(1)` after logging when any required key\n * is missing. `\"never\"` (default) returns `Left(missing)` and lets the caller\n * decide. Set to `\"missing\"` in production / staging boot paths to guarantee\n * fail-fast on misconfiguration.\n */\n readonly failOn?: \"missing\" | \"never\"\n /**\n * Logger to use. Defaults to {@link consoleBootLogger}. Any value satisfying\n * the core `Logger` interface from `functype` — including `DirectLogger`\n * from `functype-log/direct` — works without an adapter.\n */\n readonly logger?: Logger\n /** Service identifier shown in the diagnostics header. */\n readonly serviceName?: string\n}\n\n/**\n * Log a standardized boot diagnostics block and verify required-key presence.\n *\n * The block always emits, regardless of outcome — operational visibility (\"did\n * the deploy pick up my config?\") is the point. Sensitive keys are masked;\n * public keys are logged verbatim. An optional host-vs-vault env-mismatch\n * check catches the common deploy footgun where the host's `NODE_ENV` and the\n * vault's `ENV` (or equivalent) diverge.\n *\n * Returns `Either<List<MissingKey>, void>` so non-fatal callers can inspect\n * the result. Setting `failOn: \"missing\"` short-circuits to `process.exit(1)`\n * for production guards.\n *\n * @example\n * ```ts\n * const result = bootDiagnostics({\n * serviceName: \"cq-api\",\n * source: Layered([ProcessEnvSource(), await InfisicalSource(...)]),\n * required: [\"SUPABASE_URL\", \"SUPABASE_KEY\", \"OPENAI_API_KEY\"],\n * sensitive: [\"SUPABASE_URL\", \"SUPABASE_KEY\", \"OPENAI_API_KEY\"],\n * public: [\"ENV\", \"ENABLE_CHAT\"],\n * hostEnv: process.env.NODE_ENV ?? \"local\",\n * vaultEnvKey: \"ENV\",\n * failOn: process.env.NODE_ENV === \"production\" ? \"missing\" : \"never\",\n * })\n * ```\n */\nexport const bootDiagnostics = (opts: BootDiagnosticsOptions): Either<ListType<MissingKey>, void> => {\n const logger = opts.logger ?? consoleBootLogger\n const required = opts.required ?? []\n const sensitive = opts.sensitive ?? []\n const publicKeys = opts.public ?? []\n\n logger.info(`${blue(\"📦\")} Boot diagnostics: ${opts.serviceName ?? \"service\"}`)\n logger.info(` source: ${opts.source.name}`)\n\n const missing = required.filter((k) => opts.source.get(k).isEmpty)\n\n if (sensitive.length > 0) {\n logger.info(yellow(\"🔐 Sensitive:\"))\n sensitive.forEach((key) => {\n const value = opts.source.get(key)\n const display = value.fold(\n () => red(\"NOT_LOADED\"),\n (v) => maskValue(v),\n )\n logger.info(` ${key.padEnd(28)} ${display}`)\n })\n }\n\n if (publicKeys.length > 0) {\n logger.info(green(\"⚙️ Public:\"))\n publicKeys.forEach((key) => {\n const value = opts.source.get(key)\n const display = value.fold(\n () => red(\"NOT_LOADED\"),\n (v) => v,\n )\n logger.info(` ${key.padEnd(28)} ${display}`)\n })\n }\n\n if (opts.hostEnv !== undefined && opts.vaultEnvKey !== undefined) {\n const vaultEnv = opts.source.get(opts.vaultEnvKey)\n const { hostEnv } = opts\n const { vaultEnvKey } = opts\n vaultEnv.fold(\n () => {\n logger.warn(`Vault env key '${vaultEnvKey}' not present — skipping mismatch check`)\n return undefined\n },\n (v) => {\n if (v === hostEnv) {\n logger.info(`${magenta(\"🌍\")} Environment: ${hostEnv} (host) ↔ ${v} (vault) ${green(\"✓\")}`)\n } else {\n logger.error(`${magenta(\"🌍\")} Environment MISMATCH: host=${hostEnv} vault=${v}`, {\n hostEnv,\n vaultEnv: v,\n })\n }\n return undefined\n },\n )\n }\n\n if (missing.length === 0) {\n logger.info(green(\"✅ All required keys present\"))\n return Right<ListType<MissingKey>, void>(undefined)\n }\n\n logger.error(red(`❌ Missing required keys (${missing.length}):`))\n missing.forEach((key) => logger.error(` ${key}`))\n\n const missingList = List(missing.map((key): MissingKey => ({ key, required: true })))\n\n if (opts.failOn === \"missing\") {\n process.exit(1)\n }\n return Left<ListType<MissingKey>, void>(missingList)\n}\n"],"mappings":"sOA6EA,MAAa,EAAmB,GAAqE,CACnG,IAAM,EAAS,EAAK,QAAU,EACxB,EAAW,EAAK,UAAY,CAAC,EAC7B,EAAY,EAAK,WAAa,CAAC,EAC/B,EAAa,EAAK,QAAU,CAAC,EAEnC,EAAO,KAAK,GAAG,EAAK,IAAI,EAAE,qBAAqB,EAAK,aAAe,WAAW,EAC9E,EAAO,KAAK,cAAc,EAAK,OAAO,MAAM,EAE5C,IAAM,EAAU,EAAS,OAAQ,GAAM,EAAK,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,EA0BjE,GAxBI,EAAU,OAAS,IACrB,EAAO,KAAK,EAAO,eAAe,CAAC,EACnC,EAAU,QAAS,GAAQ,CAEzB,IAAM,EADQ,EAAK,OAAO,IAAI,CACV,CAAC,CAAC,SACd,EAAI,YAAY,EACrB,GAAM,EAAU,CAAC,CACpB,EACA,EAAO,KAAK,MAAM,EAAI,OAAO,EAAE,EAAE,GAAG,GAAS,CAC/C,CAAC,GAGC,EAAW,OAAS,IACtB,EAAO,KAAK,EAAM,aAAa,CAAC,EAChC,EAAW,QAAS,GAAQ,CAE1B,IAAM,EADQ,EAAK,OAAO,IAAI,CACV,CAAC,CAAC,SACd,EAAI,YAAY,EACrB,GAAM,CACT,EACA,EAAO,KAAK,MAAM,EAAI,OAAO,EAAE,EAAE,GAAG,GAAS,CAC/C,CAAC,GAGC,EAAK,UAAY,IAAA,IAAa,EAAK,cAAgB,IAAA,GAAW,CAChE,IAAM,EAAW,EAAK,OAAO,IAAI,EAAK,WAAW,EAC3C,CAAE,WAAY,EACd,CAAE,eAAgB,EACxB,EAAS,SACD,CACJ,EAAO,KAAK,kBAAkB,EAAY,wCAAwC,CAEpF,EACC,GAAM,CACD,IAAM,EACR,EAAO,KAAK,GAAG,EAAQ,IAAI,EAAE,gBAAgB,EAAQ,YAAY,EAAE,WAAW,EAAM,GAAG,GAAG,EAE1F,EAAO,MAAM,GAAG,EAAQ,IAAI,EAAE,8BAA8B,EAAQ,SAAS,IAAK,CAChF,UACA,SAAU,CACZ,CAAC,CAGL,CACF,CACF,CAEA,GAAI,EAAQ,SAAW,EAErB,OADA,EAAO,KAAK,EAAM,6BAA6B,CAAC,EACzC,EAAkC,IAAA,EAAS,EAGpD,EAAO,MAAM,EAAI,4BAA4B,EAAQ,OAAO,GAAG,CAAC,EAChE,EAAQ,QAAS,GAAQ,EAAO,MAAM,MAAM,GAAK,CAAC,EAElD,IAAM,EAAc,EAAK,EAAQ,IAAK,IAAqB,CAAE,MAAK,SAAU,EAAK,EAAE,CAAC,EAKpF,OAHI,EAAK,SAAW,WAClB,QAAQ,KAAK,CAAC,EAET,EAAiC,CAAW,CACrD"}
|
package/dist/config/colors.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=()=>process.env.NO_COLOR===void 0?process.env.FORCE_COLOR===void 0?process.stdout
|
|
1
|
+
const e=()=>process.env.NO_COLOR===void 0?process.env.FORCE_COLOR===void 0?process.stdout.isTTY:!0:!1,t=t=>n=>e()?`\x1b[${t}m${n}\x1b[0m`:n,n=t(`31`),r=t(`32`),i=t(`33`),a=t(`34`),o=t(`35`),s=t(`36`),c=t(`90`);export{a as blue,s as cyan,c as gray,r as green,o as magenta,n as red,i as yellow};
|
|
2
2
|
//# sourceMappingURL=colors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"colors.js","names":[],"sources":["../../src/config/colors.ts"],"sourcesContent":["/**\n * Internal raw-ANSI color helpers for boot diagnostics output.\n *\n * Respects established conventions:\n * - `NO_COLOR=1` (any value) → output uncolored, regardless of TTY. See\n * https://no-color.org/.\n * - `FORCE_COLOR=1` (any value) → output colored, regardless of TTY. Useful\n * for CI logs that pipe stdout but want the colors preserved.\n * - Default: color when `process.stdout.isTTY`, plain otherwise.\n *\n * Zero deps. ANSI escape codes haven't changed since 1979.\n *\n * @internal — not re-exported from the package barrel.\n */\n\nconst shouldColor = (): boolean => {\n if (process.env.NO_COLOR !== undefined) return false\n if (process.env.FORCE_COLOR !== undefined) return true\n return process.stdout
|
|
1
|
+
{"version":3,"file":"colors.js","names":[],"sources":["../../src/config/colors.ts"],"sourcesContent":["/**\n * Internal raw-ANSI color helpers for boot diagnostics output.\n *\n * Respects established conventions:\n * - `NO_COLOR=1` (any value) → output uncolored, regardless of TTY. See\n * https://no-color.org/.\n * - `FORCE_COLOR=1` (any value) → output colored, regardless of TTY. Useful\n * for CI logs that pipe stdout but want the colors preserved.\n * - Default: color when `process.stdout.isTTY`, plain otherwise.\n *\n * Zero deps. ANSI escape codes haven't changed since 1979.\n *\n * @internal — not re-exported from the package barrel.\n */\n\nconst shouldColor = (): boolean => {\n if (process.env.NO_COLOR !== undefined) return false\n if (process.env.FORCE_COLOR !== undefined) return true\n return process.stdout.isTTY\n}\n\nconst wrap =\n (code: string) =>\n (s: string): string =>\n shouldColor() ? `\\x1b[${code}m${s}\\x1b[0m` : s\n\nexport const red = wrap(\"31\")\nexport const green = wrap(\"32\")\nexport const yellow = wrap(\"33\")\nexport const blue = wrap(\"34\")\nexport const magenta = wrap(\"35\")\nexport const cyan = wrap(\"36\")\nexport const gray = wrap(\"90\")\n"],"mappings":"AAeA,MAAM,MACA,QAAQ,IAAI,WAAa,IAAA,GACzB,QAAQ,IAAI,cAAgB,IAAA,GACzB,QAAQ,OAAO,MAD4B,GADH,GAK3C,EACH,GACA,GACC,EAAY,EAAI,QAAQ,EAAK,GAAG,EAAE,SAAW,EAEpC,EAAM,EAAK,IAAI,EACf,EAAQ,EAAK,IAAI,EACjB,EAAS,EAAK,IAAI,EAClB,EAAO,EAAK,IAAI,EAChB,EAAU,EAAK,IAAI,EACnB,EAAO,EAAK,IAAI,EAChB,EAAO,EAAK,IAAI"}
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ConfigResolver } from "../ConfigResolver-
|
|
1
|
+
import { t as ConfigResolver } from "../ConfigResolver-C2SPGvWO.js";
|
|
2
2
|
import { t as ConfigSource } from "../ConfigSource-n4VKw8Vi.js";
|
|
3
3
|
import { t as Layered } from "../Layered-4k7fpktc.js";
|
|
4
4
|
import { t as ProcessEnvSource } from "../ProcessEnvSource-C9EzlVbN.js";
|
package/dist/env/Env.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as Env } from "../Env-
|
|
1
|
+
import { t as Env } from "../Env-BGw_5lWx.js";
|
|
2
2
|
export { Env };
|
package/dist/env/Env.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{EnvError as e}from"../errors/errors.js";import{Left as t,List as n,Option as r,Right as i}from"functype";const
|
|
1
|
+
import{EnvError as e}from"../errors/errors.js";import{Left as t,List as n,Option as r,Right as i,Try as a}from"functype";const o=Object.assign(e=>r(process.env[e]),{get:e=>r(process.env[e]),getRequired:t=>r(process.env[t]).toEither(e(t)),getOrDefault:(e,t)=>process.env[e]??t,has:e=>process.env[e]!==void 0,entries:()=>n(Object.entries(process.env).filter(e=>e[1]!==void 0).map(([e,t])=>[e,t])),parse:(n,o)=>{let s=r(process.env[n]);if(s.isEmpty)return t(e(n));let c=s.orThrow();return a(()=>o(c)).toEither(t=>e(n,`Failed to parse '${n}': ${t instanceof Error?t.message:String(t)}`)).flatMap(r=>typeof r==`number`&&isNaN(r)?t(e(n,`Cannot parse '${c}' as number for '${n}'`)):i(r))}});export{o as Env};
|
|
2
2
|
//# sourceMappingURL=Env.js.map
|
package/dist/env/Env.js.map
CHANGED
|
@@ -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> =>
|
|
1
|
+
{"version":3,"file":"Env.js","names":[],"sources":["../../src/env/Env.ts"],"sourcesContent":["import type { Either } from \"functype\"\nimport { Left, List, Option, Right, Try } 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> => Option(process.env[name]).toEither(EnvError(name)),\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 valueOpt = Option(process.env[name])\n if (valueOpt.isEmpty) return Left(EnvError(name))\n const value = valueOpt.orThrow()\n const parsed = Try(() => parser(value)).toEither((error) =>\n EnvError(name, `Failed to parse '${name}': ${error instanceof Error ? error.message : String(error)}`),\n )\n return parsed.flatMap((p) =>\n typeof p === \"number\" && isNaN(p)\n ? Left(EnvError(name, `Cannot parse '${value}' as number for '${name}'`))\n : Right(p),\n )\n },\n}\n\nexport const Env: typeof EnvConstructor & typeof EnvCompanion = Object.assign(EnvConstructor, EnvCompanion)\n"],"mappings":"yHAsCA,MAAa,EAAmD,OAAO,OAjC/C,GAAiC,EAAO,QAAQ,IAAI,EAAK,EAiCa,CA9B5F,IAAM,GAAiC,EAAO,QAAQ,IAAI,EAAK,EAE/D,YAAc,GAA2C,EAAO,QAAQ,IAAI,EAAK,CAAC,CAAC,SAAS,EAAS,CAAI,CAAC,EAE1G,cAAe,EAAc,IAAiC,QAAQ,IAAI,IAAS,EAEnF,IAAM,GAA0B,QAAQ,IAAI,KAAU,IAAA,GAEtD,YAIS,EAHmD,OAAO,QAAQ,QAAQ,GAAG,CAAC,CAClF,OAAQ,GAAqC,EAAM,KAAO,IAAA,EAAS,CAAC,CACpE,KAAK,CAAC,EAAG,KAAO,CAAC,EAAG,CAAC,CACR,CAAC,EAGnB,OAAW,EAAc,IAAsD,CAC7E,IAAM,EAAW,EAAO,QAAQ,IAAI,EAAK,EACzC,GAAI,EAAS,QAAS,OAAO,EAAK,EAAS,CAAI,CAAC,EAChD,IAAM,EAAQ,EAAS,QAAQ,EAI/B,OAHe,MAAU,EAAO,CAAK,CAAC,CAAC,CAAC,SAAU,GAChD,EAAS,EAAM,oBAAoB,EAAK,KAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,GAAG,CAE3F,CAAC,CAAC,QAAS,GACrB,OAAO,GAAM,UAAY,MAAM,CAAC,EAC5B,EAAK,EAAS,EAAM,iBAAiB,EAAM,mBAAmB,EAAK,EAAE,CAAC,EACtE,EAAM,CAAC,CACb,CACF,CAG4F,CAAY"}
|
package/dist/env/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as Env } from "../Env-
|
|
1
|
+
import { t as Env } from "../Env-BGw_5lWx.js";
|
|
2
2
|
export { Env };
|
package/dist/errors/errors.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as PathError, i as OsError, n as EnvError, o as ProcessError, r as FsError, t as ConfigError } from "../errors-
|
|
1
|
+
import { a as PathError, i as OsError, n as EnvError, o as ProcessError, r as FsError, t as ConfigError } from "../errors-C6fjQdSc.js";
|
|
2
2
|
export { ConfigError, EnvError, FsError, OsError, PathError, ProcessError };
|
package/dist/errors/errors.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=(e,t)=>({_tag:`EnvError`,variable:e,message:t??`Environment variable '${e}' is not set`}),t=(e,t,n)=>({_tag:`PathError`,path:e,reason:t,message:n??(t===`unresolved_variable`?`Unresolved variable in path: ${e}`:`Invalid path: ${e}`)}),n=(e,t,n)=>({_tag:`FsError`,path:e,operation:t,cause:n,message:`${t} failed for '${e}': ${n.message}`}),r=(e,t)=>({_tag:`ConfigError`,candidates:e,message:t??`No config file found among candidates: ${e.join(`, `)}`}),i=(e,t,n,r)=>({_tag:`ProcessError`,command:e,exitCode:t,stderr:n,message:r??`Command '${e}' failed (exit ${t}): ${n}`});export{r as ConfigError,e as EnvError,n as FsError,t as PathError,i as ProcessError};
|
|
1
|
+
const e=(e,t)=>({_tag:`EnvError`,variable:e,message:t??`Environment variable '${e}' is not set`}),t=(e,t,n)=>({_tag:`PathError`,path:e,reason:t,message:n??(t===`unresolved_variable`?`Unresolved variable in path: ${e}`:`Invalid path: ${e}`)}),n=(e,t,n)=>({_tag:`FsError`,path:e,operation:t,cause:n,message:`${t} failed for '${e}': ${n.message}`}),r=(e,t)=>({_tag:`ConfigError`,candidates:e,message:t??`No config file found among candidates: ${e.join(`, `)}`}),i=(e,t,n,r)=>({_tag:`ProcessError`,command:e,exitCode:t,stderr:n,message:r??`Command '${e}' failed (exit ${t.fold(()=>`?`,String)}): ${n}`});export{r as ConfigError,e as EnvError,n as FsError,t as PathError,i as ProcessError};
|
|
2
2
|
//# sourceMappingURL=errors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","names":[],"sources":["../../src/errors/errors.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"errors.js","names":[],"sources":["../../src/errors/errors.ts"],"sourcesContent":["import type { Option } from \"functype\"\n\nexport 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: Option<number>\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: Option<number>,\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.fold(() => \"?\", String)}): ${stderr}`,\n})\n"],"mappings":"AAuCA,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,SAAW,IAAK,MAAM,EAAE,KAAK,GACjG"}
|
package/dist/errors/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as PathError, i as OsError, n as EnvError, o as ProcessError, r as FsError, t as ConfigError } from "../errors-
|
|
1
|
+
import { a as PathError, i as OsError, n as EnvError, o as ProcessError, r as FsError, t as ConfigError } from "../errors-C6fjQdSc.js";
|
|
2
2
|
export { ConfigError, EnvError, FsError, type OsError, PathError, ProcessError };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Option } from "functype";
|
|
2
|
+
|
|
1
3
|
//#region src/errors/errors.d.ts
|
|
2
4
|
type EnvError = {
|
|
3
5
|
readonly _tag: "EnvError";
|
|
@@ -25,7 +27,7 @@ type ConfigError = {
|
|
|
25
27
|
type ProcessError = {
|
|
26
28
|
readonly _tag: "ProcessError";
|
|
27
29
|
readonly command: string;
|
|
28
|
-
readonly exitCode: number
|
|
30
|
+
readonly exitCode: Option<number>;
|
|
29
31
|
readonly stderr: string;
|
|
30
32
|
readonly message: string;
|
|
31
33
|
};
|
|
@@ -34,7 +36,7 @@ declare const EnvError: (variable: string, message?: string) => EnvError;
|
|
|
34
36
|
declare const PathError: (path: string, reason: PathError["reason"], message?: string) => PathError;
|
|
35
37
|
declare const FsError: (path: string, operation: string, cause: Error) => FsError;
|
|
36
38
|
declare const ConfigError: (candidates: readonly string[], message?: string) => ConfigError;
|
|
37
|
-
declare const ProcessError: (command: string, exitCode: number
|
|
39
|
+
declare const ProcessError: (command: string, exitCode: Option<number>, stderr: string, message?: string) => ProcessError;
|
|
38
40
|
//#endregion
|
|
39
41
|
export { PathError as a, OsError as i, EnvError as n, ProcessError as o, FsError as r, ConfigError as t };
|
|
40
|
-
//# sourceMappingURL=errors-
|
|
42
|
+
//# sourceMappingURL=errors-C6fjQdSc.d.ts.map
|
package/dist/fs/Fs.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as Fs, t as FileInfo } from "../Fs-
|
|
1
|
+
import { n as Fs, t as FileInfo } from "../Fs-Be3S3EHP.js";
|
|
2
2
|
export { FileInfo, Fs };
|
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
|
|
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,Try as s}from"functype";import*as c from"node:fs";import*as l from"node:fs/promises";const u=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}),d=(t,n,r)=>e(t,n,r instanceof Error?r:Error(String(r))),f=[`/proc/`,`/sys/`,`/dev/`],p=e=>f.some(t=>e.startsWith(t)),m=(e,t)=>{let n=t.replace(/[\\^$+?.()|[\]{}]/g,`\\$&`).replace(/\*\*\//g,`{{GLOBSTAR}}`).replace(/\*\*/g,`{{GLOBSTAR}}`).replace(/\*/g,`[^/]*`).replace(/\{\{GLOBSTAR\}\}/g,`(?:.*/)?`);return RegExp(`^${n}$`).test(e)},h=async(e,n,r)=>(await s.async(r)).fold(r=>Promise.resolve(t(d(e,n,r))),e=>Promise.resolve(i(e))),g=(e,t,n)=>s(n).toEither(n=>d(e,t,n)),_={exists:async e=>i((await s.async(()=>l.access(e))).isSuccess()),readFile:(e,t=`utf8`)=>h(e,`readFile`,()=>l.readFile(e,{encoding:t})),readFileOpt:async(e,n=`utf8`)=>(await s.async(()=>l.readFile(e,{encoding:n}))).fold(n=>n instanceof Error&&`code`in n&&n.code===`ENOENT`?Promise.resolve(i(a(void 0))):Promise.resolve(t(d(e,`readFile`,n))),e=>Promise.resolve(i(a(e)))),stat:e=>h(e,`stat`,()=>l.stat(e).then(u)),copyFile:(e,t)=>h(e,`copyFile`,()=>l.copyFile(e,t)),rename:(e,t)=>h(e,`rename`,()=>l.rename(e,t)),readdir:e=>h(e,`readdir`,()=>l.readdir(e).then(e=>r(e))),glob:async(e,n)=>(await s.async(()=>l.readdir(e,{recursive:!0,encoding:`utf8`}))).fold(n=>Promise.resolve(t(d(e,`glob`,n))),e=>{let t=e.filter(e=>m(e,n));return Promise.resolve(i(r(t)))}),writeFile:(e,t,n=`utf8`)=>h(e,`writeFile`,()=>l.writeFile(e,t,{encoding:n})),appendFile:(e,t,n=`utf8`)=>h(e,`appendFile`,()=>l.appendFile(e,t,{encoding:n})),mkdir:(e,n)=>n?.recursive&&p(e)?Promise.resolve(t(d(e,`mkdir`,Error(`recursive mkdir refused under magic filesystem root (/proc, /sys, /dev)`)))):h(e,`mkdir`,()=>l.mkdir(e,n).then(()=>void 0)),unlink:e=>h(e,`unlink`,()=>l.unlink(e)),existsSync:e=>s(()=>c.accessSync(e)).isSuccess(),readFileSync:(e,t=`utf8`)=>g(e,`readFileSync`,()=>c.readFileSync(e,{encoding:t})),readFileOptSync:(e,t=`utf8`)=>s(()=>c.readFileSync(e,{encoding:t})).fold(t=>t instanceof Error&&`code`in t&&t.code===`ENOENT`?o(a(void 0)):n(d(e,`readFileOptSync`,t)),e=>o(a(e))),statSync:e=>g(e,`statSync`,()=>u(c.statSync(e))),copyFileSync:(e,t)=>g(e,`copyFileSync`,()=>c.copyFileSync(e,t)),renameSync:(e,t)=>g(e,`renameSync`,()=>c.renameSync(e,t)),readdirSync:e=>g(e,`readdirSync`,()=>r(c.readdirSync(e))),writeFileSync:(e,t,n=`utf8`)=>g(e,`writeFileSync`,()=>c.writeFileSync(e,t,{encoding:n})),appendFileSync:(e,t,n=`utf8`)=>g(e,`appendFileSync`,()=>c.appendFileSync(e,t,{encoding:n})),mkdirSync:(e,t)=>t?.recursive&&p(e)?n(d(e,`mkdirSync`,Error(`recursive mkdir refused under magic filesystem root (/proc, /sys, /dev)`))):g(e,`mkdirSync`,()=>{c.mkdirSync(e,t)}),unlinkSync:e=>g(e,`unlinkSync`,()=>c.unlinkSync(e))};export{_ 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\n/**\n * Linux magic filesystems where recursive mkdir can hang indefinitely against\n * unwritable subpaths (libuv quirk; macOS errors immediately instead).\n * Refusing recursive mkdir under these prefixes keeps `mkdir({ recursive: true })`\n * fast-failing and predictable across platforms. See issue #135.\n */\nconst MAGIC_FS_PREFIXES: ReadonlyArray<string> = [\"/proc/\", \"/sys/\", \"/dev/\"]\n\nconst isMagicFsPath = (p: string): boolean => MAGIC_FS_PREFIXES.some((prefix) => p.startsWith(prefix))\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 appendFile: async (p: string, data: string, encoding: BufferEncoding = \"utf8\"): TaskResult<void> => {\n try {\n await fs.appendFile(p, data, { encoding })\n return Ok(undefined as void)\n } catch (error) {\n return Err(toFsError(p, \"appendFile\", error))\n }\n },\n\n mkdir: async (p: string, options?: { recursive?: boolean }): TaskResult<void> => {\n if (options?.recursive && isMagicFsPath(p)) {\n return Err(\n toFsError(p, \"mkdir\", new Error(\"recursive mkdir refused under magic filesystem root (/proc, /sys, /dev)\")),\n )\n }\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 appendFileSync: (p: string, data: string, encoding: BufferEncoding = \"utf8\"): Either<FsError, void> => {\n try {\n fsSync.appendFileSync(p, data, { encoding })\n return Right(undefined as void)\n } catch (error) {\n return Left(toFsError(p, \"appendFileSync\", error))\n }\n },\n\n mkdirSync: (p: string, options?: { recursive?: boolean }): Either<FsError, void> => {\n if (options?.recursive && isMagicFsPath(p)) {\n return Left(\n toFsError(p, \"mkdirSync\", new Error(\"recursive mkdir refused under magic filesystem root (/proc, /sys, /dev)\")),\n )\n }\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, Try } 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\n/**\n * Linux magic filesystems where recursive mkdir can hang indefinitely against\n * unwritable subpaths (libuv quirk; macOS errors immediately instead).\n * Refusing recursive mkdir under these prefixes keeps `mkdir({ recursive: true })`\n * fast-failing and predictable across platforms. See issue #135.\n */\nconst MAGIC_FS_PREFIXES: ReadonlyArray<string> = [\"/proc/\", \"/sys/\", \"/dev/\"]\n\nconst isMagicFsPath = (p: string): boolean => MAGIC_FS_PREFIXES.some((prefix) => p.startsWith(prefix))\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\n// Async helper: lift a Promise-returning thunk into TaskResult, mapping\n// rejections to FsError. Uses `Try.async(thunk)` rather than\n// `Try.fromPromise(thunk())` so synchronous throws from inside the thunk\n// (e.g. a bad encoding argument) are caught the same way async rejections\n// are — same Failure path, no unhandled-rejection escape hatch.\nconst liftAsync = async <T>(p: string, op: string, thunk: () => Promise<T>): TaskResult<T> => {\n const result = await Try.async(thunk)\n return result.fold<TaskResult<T>>(\n (err) => Promise.resolve(Err(toFsError(p, op, err))),\n (value) => Promise.resolve(Ok(value)),\n )\n}\n\n// Sync helper: run a thunk via Try and convert to Either<FsError, T>.\nconst liftSync = <T>(p: string, op: string, thunk: () => T): Either<FsError, T> =>\n Try(thunk).toEither((err) => toFsError(p, op, err))\n\nexport const Fs = {\n // Async methods — return TaskResult<T>\n\n exists: async (p: string): TaskResult<boolean> => {\n const result = await Try.async(() => fs.access(p))\n return Ok(result.isSuccess())\n },\n\n readFile: (p: string, encoding: BufferEncoding = \"utf8\"): TaskResult<string> =>\n liftAsync(p, \"readFile\", () => fs.readFile(p, { encoding })),\n\n readFileOpt: async (p: string, encoding: BufferEncoding = \"utf8\"): TaskResult<Option<string>> => {\n const result = await Try.async(() => fs.readFile(p, { encoding }))\n return result.fold<TaskResult<Option<string>>>(\n (err) => {\n if (err instanceof Error && \"code\" in err && err.code === \"ENOENT\") {\n return Promise.resolve(Ok(Option<string>(undefined)))\n }\n return Promise.resolve(Err(toFsError(p, \"readFile\", err)))\n },\n (data) => Promise.resolve(Ok(Option(data))),\n )\n },\n\n stat: (p: string): TaskResult<FileInfo> => liftAsync(p, \"stat\", () => fs.stat(p).then(toFileInfo)),\n\n copyFile: (src: string, dest: string): TaskResult<void> => liftAsync(src, \"copyFile\", () => fs.copyFile(src, dest)),\n\n rename: (oldPath: string, newPath: string): TaskResult<void> =>\n liftAsync(oldPath, \"rename\", () => fs.rename(oldPath, newPath)),\n\n readdir: (p: string): TaskResult<List<string>> =>\n liftAsync(p, \"readdir\", () => fs.readdir(p).then((entries) => List<string>(entries))),\n\n glob: async (dir: string, pattern: string): TaskResult<List<string>> => {\n const result = await Try.async(() => fs.readdir(dir, { recursive: true, encoding: \"utf8\" }))\n return result.fold<TaskResult<List<string>>>(\n (err) => Promise.resolve(Err(toFsError(dir, \"glob\", err))),\n (entries) => {\n const matched = (entries as string[]).filter((entry) => matchGlob(entry, pattern))\n return Promise.resolve(Ok(List<string>(matched)))\n },\n )\n },\n\n writeFile: (p: string, data: string, encoding: BufferEncoding = \"utf8\"): TaskResult<void> =>\n liftAsync(p, \"writeFile\", () => fs.writeFile(p, data, { encoding })),\n\n appendFile: (p: string, data: string, encoding: BufferEncoding = \"utf8\"): TaskResult<void> =>\n liftAsync(p, \"appendFile\", () => fs.appendFile(p, data, { encoding })),\n\n mkdir: (p: string, options?: { recursive?: boolean }): TaskResult<void> => {\n if (options?.recursive && isMagicFsPath(p)) {\n return Promise.resolve(\n Err(\n toFsError(p, \"mkdir\", new Error(\"recursive mkdir refused under magic filesystem root (/proc, /sys, /dev)\")),\n ),\n )\n }\n return liftAsync(p, \"mkdir\", () => fs.mkdir(p, options).then(() => undefined))\n },\n\n unlink: (p: string): TaskResult<void> => liftAsync(p, \"unlink\", () => fs.unlink(p)),\n\n // Sync methods — return Either<FsError, T>\n\n existsSync: (p: string): boolean => Try(() => fsSync.accessSync(p)).isSuccess(),\n\n readFileSync: (p: string, encoding: BufferEncoding = \"utf8\"): Either<FsError, string> =>\n liftSync(p, \"readFileSync\", () => fsSync.readFileSync(p, { encoding })),\n\n readFileOptSync: (p: string, encoding: BufferEncoding = \"utf8\"): Either<FsError, Option<string>> => {\n const tryResult = Try(() => fsSync.readFileSync(p, { encoding }))\n return tryResult.fold<Either<FsError, Option<string>>>(\n (err) => {\n if (err instanceof Error && \"code\" in err && err.code === \"ENOENT\") {\n return Right(Option<string>(undefined))\n }\n return Left(toFsError(p, \"readFileOptSync\", err))\n },\n (data) => Right(Option(data)),\n )\n },\n\n statSync: (p: string): Either<FsError, FileInfo> => liftSync(p, \"statSync\", () => toFileInfo(fsSync.statSync(p))),\n\n copyFileSync: (src: string, dest: string): Either<FsError, void> =>\n liftSync(src, \"copyFileSync\", () => fsSync.copyFileSync(src, dest)),\n\n renameSync: (oldPath: string, newPath: string): Either<FsError, void> =>\n liftSync(oldPath, \"renameSync\", () => fsSync.renameSync(oldPath, newPath)),\n\n readdirSync: (p: string): Either<FsError, List<string>> =>\n liftSync(p, \"readdirSync\", () => List(fsSync.readdirSync(p))),\n\n writeFileSync: (p: string, data: string, encoding: BufferEncoding = \"utf8\"): Either<FsError, void> =>\n liftSync(p, \"writeFileSync\", () => fsSync.writeFileSync(p, data, { encoding })),\n\n appendFileSync: (p: string, data: string, encoding: BufferEncoding = \"utf8\"): Either<FsError, void> =>\n liftSync(p, \"appendFileSync\", () => fsSync.appendFileSync(p, data, { encoding })),\n\n mkdirSync: (p: string, options?: { recursive?: boolean }): Either<FsError, void> => {\n if (options?.recursive && isMagicFsPath(p)) {\n return Left(\n toFsError(p, \"mkdirSync\", new Error(\"recursive mkdir refused under magic filesystem root (/proc, /sys, /dev)\")),\n )\n }\n return liftSync(p, \"mkdirSync\", () => {\n fsSync.mkdirSync(p, options)\n })\n },\n\n unlinkSync: (p: string): Either<FsError, void> => liftSync(p, \"unlinkSync\", () => fsSync.unlinkSync(p)),\n}\n"],"mappings":"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"}
|
package/dist/fs/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as Fs, t as FileInfo } from "../Fs-
|
|
1
|
+
import { n as Fs, t as FileInfo } from "../Fs-Be3S3EHP.js";
|
|
2
2
|
export { type FileInfo, Fs };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as PathError, i as OsError, n as EnvError, o as ProcessError, r as FsError, t as ConfigError } from "./errors-
|
|
2
|
-
import { t as ConfigResolver } from "./ConfigResolver-
|
|
3
|
-
import { t as Env } from "./Env-
|
|
4
|
-
import { n as Fs, t as FileInfo } from "./Fs-
|
|
5
|
-
import { i as expandVars, n as expandPath, r as expandTilde, t as Path } from "./PathExpander-
|
|
6
|
-
import { i as UserInfo, n as CloudStorageDir, r as Platform, t as CloudProvider } from "./Platform-
|
|
7
|
-
import { n as Process, t as ExecResult } from "./Process-
|
|
1
|
+
import { a as PathError, i as OsError, n as EnvError, o as ProcessError, r as FsError, t as ConfigError } from "./errors-C6fjQdSc.js";
|
|
2
|
+
import { t as ConfigResolver } from "./ConfigResolver-C2SPGvWO.js";
|
|
3
|
+
import { t as Env } from "./Env-BGw_5lWx.js";
|
|
4
|
+
import { n as Fs, t as FileInfo } from "./Fs-Be3S3EHP.js";
|
|
5
|
+
import { i as expandVars, n as expandPath, r as expandTilde, t as Path } from "./PathExpander-CjiEMvqX.js";
|
|
6
|
+
import { i as UserInfo, n as CloudStorageDir, r as Platform, t as CloudProvider } from "./Platform-DotricJv.js";
|
|
7
|
+
import { n as Process, t as ExecResult } from "./Process-WxEgO5iR.js";
|
|
8
8
|
export { type CloudProvider, type CloudStorageDir, ConfigError, ConfigResolver, Env, EnvError, type ExecResult, type FileInfo, Fs, FsError, type OsError, Path, PathError, Platform, Process, ProcessError, type UserInfo, expandPath, expandTilde, expandVars };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as expandVars, n as expandPath, r as expandTilde, t as Path } from "../PathExpander-
|
|
1
|
+
import { i as expandVars, n as expandPath, r as expandTilde, t as Path } from "../PathExpander-CjiEMvqX.js";
|
|
2
2
|
export { Path, expandPath, expandTilde, expandVars };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{PathError as e}from"../errors/errors.js";import{Left as t,Right as
|
|
1
|
+
import{PathError as e}from"../errors/errors.js";import{Left as t,Option as n,Right as r}from"functype";import*as i from"node:os";import*as a from"node:path";const o=e=>e===`~`?i.homedir():e.startsWith(`~/`)||e.startsWith(`~\\`)?a.join(i.homedir(),e.slice(2)):e,s=i=>{let a=[],o=i.replace(/\$(?:\{([^}$]+)\}|([A-Za-z_][A-Za-z0-9_]*))/g,(e,...t)=>{let r=n(t[0]).or(n(t[1])).orElse(``),i=process.env[r];return i===void 0?(a.push(r),e):i});return a.length>0?t(e(i,`unresolved_variable`,`Unresolved variables: ${a.join(`, `)}`)):r(o)},c=e=>{let t=s(o(e));return t.isLeft()?t:r(a.resolve(t.orThrow()))},l={expand:c,expandTilde:o,expandVars:s,join:(...e)=>a.join(...e),resolve:(...e)=>a.resolve(...e),dirname:e=>a.dirname(e),basename:(e,t)=>a.basename(e,t),extname:e=>a.extname(e),isAbsolute:e=>a.isAbsolute(e)};export{l as Path,c as expandPath,o as expandTilde,s 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 // 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(
|
|
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, Option, 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(/\\$(?:\\{([^}$]+)\\}|([A-Za-z_][A-Za-z0-9_]*))/g, (_match: string, ...captures: unknown[]) => {\n const varName = Option(captures[0] as string | undefined)\n .or(Option(captures[1] as string | undefined))\n .orElse(\"\")\n const value = process.env[varName]\n if (value === undefined) {\n unresolvedVars.push(varName)\n return _match\n }\n return value\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":"6JAQA,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,QAAQ,gDAAiD,EAAgB,GAAG,IAAwB,CACnH,IAAM,EAAU,EAAO,EAAS,EAAwB,CAAC,CACtD,GAAG,EAAO,EAAS,EAAwB,CAAC,CAAC,CAC7C,OAAO,EAAE,EACN,EAAQ,QAAQ,IAAI,GAK1B,OAJI,IAAU,IAAA,IACZ,EAAe,KAAK,CAAO,EACpB,GAEF,CACT,CAAC,EAMD,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"}
|
package/dist/path/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as expandVars, n as expandPath, r as expandTilde, t as Path } from "../PathExpander-
|
|
1
|
+
import { i as expandVars, n as expandPath, r as expandTilde, t as Path } from "../PathExpander-CjiEMvqX.js";
|
|
2
2
|
export { Path, expandPath, expandTilde, expandVars };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as UserInfo, n as CloudStorageDir, r as Platform, t as CloudProvider } from "../Platform-
|
|
1
|
+
import { i as UserInfo, n as CloudStorageDir, r as Platform, t as CloudProvider } from "../Platform-DotricJv.js";
|
|
2
2
|
export { CloudProvider, CloudStorageDir, Platform, UserInfo };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{List as e,Option as t}from"functype";import*as
|
|
1
|
+
import{List as e,Option as t,Set as n,Try as r}from"functype";import*as i from"node:fs";import*as a from"node:os";import*as o from"node:path";import{execSync as s}from"node:child_process";const c=()=>r(()=>i.statSync(`/.dockerenv`)).isSuccess(),l=()=>r(()=>i.readFileSync(`/proc/self/cgroup`,`utf8`)).map(e=>e.includes(`docker`)).toEither(()=>!1).fold(()=>!1,e=>e),u=e=>{let t={};return()=>(`value`in t||(t.value=e()),t.value)},d=u(()=>c()||l()),f=u(()=>r(()=>i.readFileSync(`/proc/self/cgroup`,`utf8`)).map(e=>e.includes(`kube`)).fold(()=>!1,e=>e)),p=u(()=>r(()=>i.readFileSync(`/proc/version`,`utf8`)).map(e=>e.includes(`Microsoft`)||e.includes(`WSL`)).fold(()=>!1,e=>e)),m=u(()=>process.env.CI!==void 0||process.env.GITHUB_ACTIONS!==void 0||process.env.GITLAB_CI!==void 0||process.env.CIRCLECI!==void 0||process.env.JENKINS_URL!==void 0||process.env.TRAVIS!==void 0||process.env.BUILDKITE!==void 0),h=n.of(`all users`,`default`,`default user`,`public`),g=e=>{let t=e.toLowerCase();return!!(h.contains(t)||t.startsWith(`defaultuser`)||t.startsWith(`desktop.`)||t.startsWith(`wsiaccount`))},_=e=>r(()=>i.statSync(e).isDirectory()).fold(()=>!1,e=>e),v=e=>r(()=>i.readdirSync(e)).map(t=>t.filter(t=>!g(t)&&_(o.join(e,t)))).toOption(),y=(e,n)=>t(r(()=>s(`cmd.exe /c echo %USERPROFILE%`,{timeout:3e3,encoding:`utf8`}).trim()).toOption().flatMap(e=>{let n=e.match(/^([A-Za-z]):\\(.*)$/);if(!n)return t(void 0);let r=`/mnt/${n[1].toLowerCase()}/${n[2].replace(/\\/g,`/`)}`;return _(r)?t(r):t(void 0)}).orElse(n)),b=u(()=>{if(!p())return t(void 0);let e=`/mnt/c/Users`;return v(e).fold(()=>t(void 0),n=>n.length===1?t(o.join(e,n[0])):n.length>1?y(e,o.join(e,n[0])):t(void 0))}),x=e=>e===`OneDrive`||e.startsWith(`OneDrive `)||e.startsWith(`OneDrive-`)?t({provider:`onedrive`,label:e}):t(e===`Google Drive`?{provider:`gdrive`,label:e}:e===`Dropbox`?{provider:`dropbox`,label:e}:void 0),S=e=>r(()=>i.readdirSync(e)).map(t=>t.flatMap(t=>{let n=o.join(e,t);return x(t).fold(()=>[],e=>_(n)?[{provider:e.provider,path:n,label:e.label}]:[])})).fold(()=>[],e=>e),C=e=>{let t=o.join(e,`Library`,`CloudStorage`);return r(()=>i.readdirSync(t)).map(e=>e.flatMap(e=>{let n=o.join(t,e);return _(n)?e.startsWith(`OneDrive`)?[{provider:`onedrive`,path:n,label:e}]:e.startsWith(`GoogleDrive`)?[{provider:`gdrive`,path:n,label:e}]:[]:[]})).fold(()=>[],e=>e)},w=e=>{let t=o.join(e,`Library`,`Mobile Documents`,`com~apple~CloudDocs`);return _(t)?[{provider:`icloud`,path:t,label:`iCloud Drive`}]:[]},T=e=>[...S(e),...C(e),...w(e)],E={os:()=>process.platform,arch:()=>process.arch,homeDir:()=>a.homedir(),tmpDir:()=>a.tmpdir(),hostname:()=>a.hostname(),eol:()=>a.EOL,pathSep:()=>o.sep,isWindows:()=>process.platform===`win32`,isMac:()=>process.platform===`darwin`,isLinux:()=>process.platform===`linux`,userInfo:()=>r(()=>a.userInfo()).map(e=>({username:e.username,uid:e.uid,gid:e.gid,shell:t(e.shell),homedir:e.homedir})).toOption(),isDocker:()=>d(),isKubernetes:()=>f(),isWSL:()=>p(),isCI:()=>m(),isContainer:()=>E.isDocker()||E.isKubernetes(),windowsHomeDir:()=>b(),homeDirs:()=>{let t=a.homedir();return e([t,...E.windowsHomeDir().fold(()=>[],e=>e===t?[]:[e])])},cloudStorageDirs:t=>e(t===void 0?E.homeDirs().toArray().flatMap(e=>[...T(e)]).reduce((e,t)=>e.seen.includes(t.path)?e:{seen:[...e.seen,t.path],results:[...e.results,t]},{seen:[],results:[]}).results:T(t))};export{E as Platform};
|
|
2
2
|
//# sourceMappingURL=Platform.js.map
|
|
@@ -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":["FSet"],"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, Set as FSet, Try } from \"functype\"\n\nexport type UserInfo = {\n readonly username: string\n readonly uid: number\n readonly gid: number\n readonly shell: Option<string>\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 => Try(() => fs.statSync(\"/.dockerenv\")).isSuccess()\n\nconst hasDockerCGroup = (): boolean =>\n Try(() => fs.readFileSync(\"/proc/self/cgroup\", \"utf8\"))\n .map((contents) => contents.includes(\"docker\"))\n .toEither((): boolean => false)\n .fold(\n () => false,\n (matched) => matched,\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(() => fs.readFileSync(\"/proc/self/cgroup\", \"utf8\"))\n .map((contents) => contents.includes(\"kube\"))\n .fold(\n () => false,\n (matched) => matched,\n ),\n)\nconst cachedIsWSL = memo(() =>\n Try(() => fs.readFileSync(\"/proc/version\", \"utf8\"))\n .map((version) => version.includes(\"Microsoft\") || version.includes(\"WSL\"))\n .fold(\n () => false,\n (matched) => matched,\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 = FSet.of(\"all users\", \"default\", \"default user\", \"public\")\n\nconst isSystemAccount = (name: string): boolean => {\n const lower = name.toLowerCase()\n if (SYSTEM_ACCOUNTS.contains(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(() => fs.statSync(p).isDirectory()).fold(\n () => false,\n (isDir) => isDir,\n )\n\nconst readRealUsers = (usersDir: string): Option<readonly string[]> => {\n const filterRealUsers = (entries: readonly string[]): readonly string[] =>\n entries.filter((name) => !isSystemAccount(name) && isDirectory(path.join(usersDir, name)))\n return Try(() => fs.readdirSync(usersDir))\n .map(filterRealUsers)\n .toOption()\n}\n\nconst resolveViaCmdExe = (usersDir: string, fallback: string): Option<string> => {\n // Convert Windows path C:\\Users\\foo → /mnt/c/Users/foo if it's a directory;\n // returns None for unparseable output or non-existent directories.\n const parseCmdOutput = (raw: string): Option<string> => {\n const match = raw.match(/^([A-Za-z]):\\\\(.*)$/)\n if (!match) return Option<string>(undefined)\n const drive = (match[1] as string).toLowerCase()\n const rest = (match[2] as string).replace(/\\\\/g, \"/\")\n const wslPath = `/mnt/${drive}/${rest}`\n return isDirectory(wslPath) ? Option(wslPath) : Option<string>(undefined)\n }\n const parsed = Try(() => execSync(\"cmd.exe /c echo %USERPROFILE%\", { timeout: 3000, encoding: \"utf8\" }).trim())\n .toOption()\n .flatMap(parseCmdOutput)\n .orElse(fallback)\n return Option(parsed)\n}\n\nconst resolveWindowsHome = (): Option<string> => {\n if (!cachedIsWSL()) return Option<string>(undefined)\n\n const usersDir = \"/mnt/c/Users\"\n return readRealUsers(usersDir).fold<Option<string>>(\n () => Option<string>(undefined),\n (realUsers) => {\n if (realUsers.length === 1) return Option(path.join(usersDir, realUsers[0] as string))\n if (realUsers.length > 1) return resolveViaCmdExe(usersDir, path.join(usersDir, realUsers[0] as string))\n return Option<string>(undefined)\n },\n )\n}\n\nconst cachedWindowsHome = memo(resolveWindowsHome)\n\ntype CloudDetection = { readonly provider: CloudProvider; readonly label: string }\n\nconst detectCloudProvider = (name: string): Option<CloudDetection> => {\n if (name === \"OneDrive\" || name.startsWith(\"OneDrive \") || name.startsWith(\"OneDrive-\")) {\n return Option({ provider: \"onedrive\" as const, label: name })\n }\n if (name === \"Google Drive\") return Option({ provider: \"gdrive\" as const, label: name })\n if (name === \"Dropbox\") return Option({ provider: \"dropbox\" as const, label: name })\n return Option<CloudDetection>(undefined)\n}\n\nconst scanDirectChildren = (home: string): readonly CloudStorageDir[] =>\n Try(() => fs.readdirSync(home))\n .map((entries) =>\n entries.flatMap((name): CloudStorageDir[] => {\n const fullPath = path.join(home, name)\n return detectCloudProvider(name).fold<CloudStorageDir[]>(\n () => [],\n (detection) =>\n isDirectory(fullPath) ? [{ provider: detection.provider, path: fullPath, label: detection.label }] : [],\n )\n }),\n )\n .fold<readonly CloudStorageDir[]>(\n () => [],\n (results) => results,\n )\n\nconst scanMacCloudStorage = (home: string): readonly CloudStorageDir[] => {\n const cloudStoragePath = path.join(home, \"Library\", \"CloudStorage\")\n return Try(() => fs.readdirSync(cloudStoragePath))\n .map((entries) =>\n entries.flatMap((name): CloudStorageDir[] => {\n const fullPath = path.join(cloudStoragePath, name)\n if (!isDirectory(fullPath)) return []\n if (name.startsWith(\"OneDrive\")) return [{ provider: \"onedrive\", path: fullPath, label: name }]\n if (name.startsWith(\"GoogleDrive\")) return [{ provider: \"gdrive\", path: fullPath, label: name }]\n return []\n }),\n )\n .fold<readonly CloudStorageDir[]>(\n () => [],\n (results) => results,\n )\n}\n\nconst scanMacICloud = (home: string): readonly CloudStorageDir[] => {\n const icloudPath = path.join(home, \"Library\", \"Mobile Documents\", \"com~apple~CloudDocs\")\n return isDirectory(icloudPath) ? [{ provider: \"icloud\", path: icloudPath, label: \"iCloud Drive\" }] : []\n}\n\nconst scanCloudStorageDirs = (home: string): readonly CloudStorageDir[] => [\n ...scanDirectChildren(home),\n ...scanMacCloudStorage(home),\n ...scanMacICloud(home),\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 const toUserInfo = (info: os.UserInfo<string>): UserInfo => ({\n username: info.username,\n uid: info.uid,\n gid: info.gid,\n shell: Option(info.shell),\n homedir: info.homedir,\n })\n return Try(() => os.userInfo())\n .map(toUserInfo)\n .toOption()\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 primary = os.homedir()\n const windowsHome = Platform.windowsHomeDir().fold<readonly string[]>(\n () => [],\n (h) => (h !== primary ? [h] : []),\n )\n return List<string>([primary, ...windowsHome])\n },\n\n cloudStorageDirs: (home?: string): List<CloudStorageDir> => {\n if (home !== undefined) return List(scanCloudStorageDirs(home))\n const allDirs = Platform.homeDirs()\n .toArray()\n .flatMap((h) => [...scanCloudStorageDirs(h)])\n // Deduplicate by path, first-wins\n const deduped = allDirs.reduce<{\n readonly seen: ReadonlyArray<string>\n readonly results: ReadonlyArray<CloudStorageDir>\n }>(\n (acc, dir) =>\n acc.seen.includes(dir.path) ? acc : { seen: [...acc.seen, dir.path], results: [...acc.results, dir] },\n { seen: [], results: [] },\n )\n return List(deduped.results)\n },\n}\n"],"mappings":"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"}
|
package/dist/platform/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as UserInfo, n as CloudStorageDir, r as Platform, t as CloudProvider } from "../Platform-
|
|
1
|
+
import { i as UserInfo, n as CloudStorageDir, r as Platform, t as CloudProvider } from "../Platform-DotricJv.js";
|
|
2
2
|
export { type CloudProvider, type CloudStorageDir, Platform, type UserInfo };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as Process, t as ExecResult } from "../Process-
|
|
1
|
+
import { n as Process, t as ExecResult } from "../Process-WxEgO5iR.js";
|
|
2
2
|
export { ExecResult, Process };
|
package/dist/process/Process.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ProcessError as e}from"../errors/errors.js";import{Err as t,
|
|
1
|
+
import{ProcessError as e}from"../errors/errors.js";import{Err as t,Ok as n,Option as r,Try as i}from"functype";import{exec as a,execSync as o}from"node:child_process";const s={exec:(i,o)=>new Promise(s=>{a(i,{timeout:o?.timeout,cwd:o?.cwd},(a,o,c)=>{s(a?t(e(i,r(typeof a.code==`number`?a.code:void 0),String(c))):n({stdout:String(o),stderr:String(c),exitCode:0}))})}),execSync:(t,n)=>i(()=>o(t,{timeout:n?.timeout,cwd:n?.cwd,encoding:`utf8`,stdio:[`pipe`,`pipe`,`pipe`]})).toEither(n=>{if(n instanceof Error&&`status`in n&&`stderr`in n){let i=n;return e(t,r(i.status),String(i.stderr))}return e(t,r(void 0),``,n instanceof Error?n.message:String(n))}).map(e=>({stdout:String(e),stderr:``,exitCode:0}))};export{s as Process};
|
|
2
2
|
//# sourceMappingURL=Process.js.map
|
|
@@ -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,
|
|
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, Ok, Option, Try } 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 = Option(typeof error.code === \"number\" ? error.code : undefined)\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 const buildProcessError = (error: unknown): ProcessError => {\n if (error instanceof Error && \"status\" in error && \"stderr\" in error) {\n const execError = error as Error & { status: number; stderr: string }\n return ProcessError(command, Option(execError.status), String(execError.stderr))\n }\n return ProcessError(\n command,\n Option<number>(undefined),\n \"\",\n error instanceof Error ? error.message : String(error),\n )\n }\n return Try(() =>\n nodeExecSync(command, {\n timeout: options?.timeout,\n cwd: options?.cwd,\n encoding: \"utf8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }),\n )\n .toEither(buildProcessError)\n .map((stdout): ExecResult => ({ stdout: String(stdout), stderr: \"\", exitCode: 0 }))\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,EAAO,OAAO,EAAM,MAAS,SAAW,EAAM,KAAO,IAAA,EAC7B,EAAG,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,IAanB,MACLA,EAAa,EAAS,CACpB,QAAS,GAAS,QAClB,IAAK,GAAS,IACd,SAAU,OACV,MAAO,CAAC,OAAQ,OAAQ,MAAM,CAChC,CAAC,CACH,CAAC,CACE,SApBwB,GAAiC,CAC1D,GAAI,aAAiB,OAAS,WAAY,GAAS,WAAY,EAAO,CACpE,IAAM,EAAY,EAClB,OAAO,EAAa,EAAS,EAAO,EAAU,MAAM,EAAG,OAAO,EAAU,MAAM,CAAC,CACjF,CACA,OAAO,EACL,EACA,EAAe,IAAA,EAAS,EACxB,GACA,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CACvD,CACF,CAS6B,CAAC,CAC3B,IAAK,IAAwB,CAAE,OAAQ,OAAO,CAAM,EAAG,OAAQ,GAAI,SAAU,CAAE,EAAE,CAExF"}
|
package/dist/process/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as Process, t as ExecResult } from "../Process-
|
|
1
|
+
import { n as Process, t as ExecResult } from "../Process-WxEgO5iR.js";
|
|
2
2
|
export { type ExecResult, Process };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "functype-os",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "Functional OS utilities using functype data structures — env vars, path expansion, file ops, platform detection",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"functype",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"functype": ">=0.60.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@types/node": "^24.
|
|
29
|
+
"@types/node": "^24.13.2",
|
|
30
30
|
"eslint-config-prettier": "^10.1.8",
|
|
31
|
-
"ts-builds": "^3.
|
|
32
|
-
"tsdown": "^0.22.
|
|
31
|
+
"ts-builds": "^3.1.0",
|
|
32
|
+
"tsdown": "^0.22.2",
|
|
33
33
|
"vitest": "^4.1.8",
|
|
34
|
-
"functype": "^1.
|
|
34
|
+
"functype": "^1.4.1"
|
|
35
35
|
},
|
|
36
36
|
"type": "module",
|
|
37
37
|
"main": "./dist/index.js",
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
"format": "ts-builds format",
|
|
97
97
|
"format:check": "ts-builds format:check",
|
|
98
98
|
"lint": "ts-builds lint",
|
|
99
|
-
"lint:check": "
|
|
99
|
+
"lint:check": "eslint src --max-warnings 0",
|
|
100
100
|
"typecheck": "ts-builds typecheck",
|
|
101
101
|
"test": "ts-builds test",
|
|
102
102
|
"test:watch": "ts-builds test:watch",
|