mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 08:58:37 +00:00
fix(config): coerce numeric meta.lastTouchedAt to ISO string
This commit is contained in:
committed by
Peter Steinberger
parent
b5787e4abb
commit
2c4ebf77f3
70
src/config/config.meta-timestamp-coercion.test.ts
Normal file
70
src/config/config.meta-timestamp-coercion.test.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import { describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
describe("meta.lastTouchedAt numeric timestamp coercion", () => {
|
||||||
|
it("accepts a numeric Unix timestamp and coerces it to an ISO string", async () => {
|
||||||
|
vi.resetModules();
|
||||||
|
const { validateConfigObject } = await import("./config.js");
|
||||||
|
const numericTimestamp = 1770394758161;
|
||||||
|
const res = validateConfigObject({
|
||||||
|
meta: {
|
||||||
|
lastTouchedAt: numericTimestamp,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(res.ok).toBe(true);
|
||||||
|
if (res.ok) {
|
||||||
|
expect(typeof res.config.meta?.lastTouchedAt).toBe("string");
|
||||||
|
expect(res.config.meta?.lastTouchedAt).toBe(new Date(numericTimestamp).toISOString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("still accepts a string ISO timestamp unchanged", async () => {
|
||||||
|
vi.resetModules();
|
||||||
|
const { validateConfigObject } = await import("./config.js");
|
||||||
|
const isoTimestamp = "2026-02-07T01:39:18.161Z";
|
||||||
|
const res = validateConfigObject({
|
||||||
|
meta: {
|
||||||
|
lastTouchedAt: isoTimestamp,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(res.ok).toBe(true);
|
||||||
|
if (res.ok) {
|
||||||
|
expect(res.config.meta?.lastTouchedAt).toBe(isoTimestamp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects out-of-range numeric timestamps without throwing", async () => {
|
||||||
|
vi.resetModules();
|
||||||
|
const { validateConfigObject } = await import("./config.js");
|
||||||
|
const res = validateConfigObject({
|
||||||
|
meta: {
|
||||||
|
lastTouchedAt: 1e20,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(res.ok).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("passes non-date strings through unchanged (backwards-compatible)", async () => {
|
||||||
|
vi.resetModules();
|
||||||
|
const { validateConfigObject } = await import("./config.js");
|
||||||
|
const res = validateConfigObject({
|
||||||
|
meta: {
|
||||||
|
lastTouchedAt: "not-a-date",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(res.ok).toBe(true);
|
||||||
|
if (res.ok) {
|
||||||
|
expect(res.config.meta?.lastTouchedAt).toBe("not-a-date");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("accepts meta with only lastTouchedVersion (no lastTouchedAt)", async () => {
|
||||||
|
vi.resetModules();
|
||||||
|
const { validateConfigObject } = await import("./config.js");
|
||||||
|
const res = validateConfigObject({
|
||||||
|
meta: {
|
||||||
|
lastTouchedVersion: "2026.2.6",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(res.ok).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -129,7 +129,21 @@ export const OpenClawSchema = z
|
|||||||
meta: z
|
meta: z
|
||||||
.object({
|
.object({
|
||||||
lastTouchedVersion: z.string().optional(),
|
lastTouchedVersion: z.string().optional(),
|
||||||
lastTouchedAt: z.string().optional(),
|
// Accept any string unchanged (backwards-compatible) and coerce numeric Unix
|
||||||
|
// timestamps to ISO strings (agent file edits may write Date.now()).
|
||||||
|
lastTouchedAt: z
|
||||||
|
.union([
|
||||||
|
z.string(),
|
||||||
|
z.number().transform((n, ctx) => {
|
||||||
|
const d = new Date(n);
|
||||||
|
if (Number.isNaN(d.getTime())) {
|
||||||
|
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Invalid timestamp" });
|
||||||
|
return z.NEVER;
|
||||||
|
}
|
||||||
|
return d.toISOString();
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
.optional(),
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
.optional(),
|
.optional(),
|
||||||
|
|||||||
Reference in New Issue
Block a user