mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-07 07:58:36 +00:00
* refactor: extract filesystem safety primitives * refactor: use fs-safe for file access helpers * refactor: reuse fs-safe for media reads * refactor: use fs-safe for image reads * refactor: reuse fs-safe in qqbot media opener * refactor: reuse fs-safe for local media checks * refactor: consume cleaner fs-safe api * refactor: align fs-safe json option names * fix: preserve fs-safe migration contracts * refactor: use fs-safe primitive subpaths * refactor: use grouped fs-safe subpaths * refactor: align fs-safe api usage * refactor: adapt private state store api * chore: refresh proof gate * refactor: follow fs-safe json api split * refactor: follow reduced fs-safe surface * build: default fs-safe python helper off * fix: preserve fs-safe plugin sdk aliases * refactor: consolidate fs-safe usage * refactor: unify fs-safe store usage * refactor: trim fs-safe temp workspace usage * refactor: hide low-level fs-safe primitives * build: use published fs-safe package * fix: preserve outbound recovery durability after rebase * chore: refresh pr checks
69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { privateFileStoreSync } from "../infra/private-file-store.js";
|
|
import { replaceFileAtomicSync } from "../infra/replace-file.js";
|
|
export { isRecord } from "../utils.js";
|
|
|
|
export function isNonEmptyString(value: unknown): value is string {
|
|
return typeof value === "string" && value.trim().length > 0;
|
|
}
|
|
|
|
export function parseEnvValue(raw: string): string {
|
|
const trimmed = raw.trim();
|
|
if (
|
|
(trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
(trimmed.startsWith("'") && trimmed.endsWith("'"))
|
|
) {
|
|
return trimmed.slice(1, -1);
|
|
}
|
|
return trimmed;
|
|
}
|
|
|
|
export function normalizePositiveInt(value: unknown, fallback: number): number {
|
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
return Math.max(1, Math.floor(value));
|
|
}
|
|
return Math.max(1, Math.floor(fallback));
|
|
}
|
|
|
|
export function parseDotPath(pathname: string): string[] {
|
|
return pathname
|
|
.split(".")
|
|
.map((segment) => segment.trim())
|
|
.filter((segment) => segment.length > 0);
|
|
}
|
|
|
|
export function toDotPath(segments: string[]): string {
|
|
return segments.join(".");
|
|
}
|
|
|
|
export function ensureDirForFile(filePath: string): void {
|
|
fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
|
|
}
|
|
|
|
export function writeJsonFileSecure(pathname: string, value: unknown): void {
|
|
privateFileStoreSync(path.dirname(pathname)).writeJson(path.basename(pathname), value, {
|
|
trailingNewline: true,
|
|
});
|
|
}
|
|
|
|
export function readTextFileIfExists(pathname: string): string | null {
|
|
if (!fs.existsSync(pathname)) {
|
|
return null;
|
|
}
|
|
return fs.readFileSync(pathname, "utf8");
|
|
}
|
|
|
|
export function writeTextFileAtomic(pathname: string, value: string, mode = 0o600): void {
|
|
if (mode !== 0o600) {
|
|
replaceFileAtomicSync({
|
|
filePath: pathname,
|
|
content: value,
|
|
mode,
|
|
tempPrefix: ".openclaw-secrets",
|
|
});
|
|
return;
|
|
}
|
|
privateFileStoreSync(path.dirname(pathname)).writeText(path.basename(pathname), value);
|
|
}
|