mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 09:11:26 +00:00
refactor: share plain object guard across config and utils
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
import { isPlainObject } from "../infra/plain-object.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preserves `${VAR}` environment variable references during config write-back.
|
* Preserves `${VAR}` environment variable references during config write-back.
|
||||||
*
|
*
|
||||||
@@ -16,15 +18,6 @@
|
|||||||
|
|
||||||
const ENV_VAR_PATTERN = /\$\{[A-Z_][A-Z0-9_]*\}/;
|
const ENV_VAR_PATTERN = /\$\{[A-Z_][A-Z0-9_]*\}/;
|
||||||
|
|
||||||
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
||||||
return (
|
|
||||||
typeof value === "object" &&
|
|
||||||
value !== null &&
|
|
||||||
!Array.isArray(value) &&
|
|
||||||
Object.prototype.toString.call(value) === "[object Object]"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a string contains any `${VAR}` env var references.
|
* Check if a string contains any `${VAR}` env var references.
|
||||||
*/
|
*/
|
||||||
|
|||||||
18
src/infra/plain-object.test.ts
Normal file
18
src/infra/plain-object.test.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { isPlainObject } from "./plain-object.js";
|
||||||
|
|
||||||
|
describe("isPlainObject", () => {
|
||||||
|
it("accepts plain objects", () => {
|
||||||
|
expect(isPlainObject({})).toBe(true);
|
||||||
|
expect(isPlainObject({ a: 1 })).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects non-plain values", () => {
|
||||||
|
expect(isPlainObject(null)).toBe(false);
|
||||||
|
expect(isPlainObject([])).toBe(false);
|
||||||
|
expect(isPlainObject(new Date())).toBe(false);
|
||||||
|
expect(isPlainObject(/re/)).toBe(false);
|
||||||
|
expect(isPlainObject("x")).toBe(false);
|
||||||
|
expect(isPlainObject(42)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
11
src/infra/plain-object.ts
Normal file
11
src/infra/plain-object.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Strict plain-object guard (excludes arrays and host objects).
|
||||||
|
*/
|
||||||
|
export function isPlainObject(value: unknown): value is Record<string, unknown> {
|
||||||
|
return (
|
||||||
|
typeof value === "object" &&
|
||||||
|
value !== null &&
|
||||||
|
!Array.isArray(value) &&
|
||||||
|
Object.prototype.toString.call(value) === "[object Object]"
|
||||||
|
);
|
||||||
|
}
|
||||||
14
src/utils.ts
14
src/utils.ts
@@ -8,6 +8,7 @@ import {
|
|||||||
resolveEffectiveHomeDir,
|
resolveEffectiveHomeDir,
|
||||||
resolveRequiredHomeDir,
|
resolveRequiredHomeDir,
|
||||||
} from "./infra/home-dir.js";
|
} from "./infra/home-dir.js";
|
||||||
|
import { isPlainObject } from "./infra/plain-object.js";
|
||||||
|
|
||||||
export async function ensureDir(dir: string) {
|
export async function ensureDir(dir: string) {
|
||||||
await fs.promises.mkdir(dir, { recursive: true });
|
await fs.promises.mkdir(dir, { recursive: true });
|
||||||
@@ -54,18 +55,7 @@ export function safeParseJson<T>(raw: string): T | null {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export { isPlainObject };
|
||||||
* Type guard for plain objects (not arrays, null, Date, RegExp, etc.).
|
|
||||||
* Uses Object.prototype.toString for maximum safety.
|
|
||||||
*/
|
|
||||||
export function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
||||||
return (
|
|
||||||
typeof value === "object" &&
|
|
||||||
value !== null &&
|
|
||||||
!Array.isArray(value) &&
|
|
||||||
Object.prototype.toString.call(value) === "[object Object]"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type guard for Record<string, unknown> (less strict than isPlainObject).
|
* Type guard for Record<string, unknown> (less strict than isPlainObject).
|
||||||
|
|||||||
Reference in New Issue
Block a user