refactor: duration fields → number|null (milliseconds)
- throttle, timeout, interval: string|null → number|null - parseDurationField now returns parsed ms (5s→5000, 10m→600000, 1h→3600000) - biome.json: ignore dist/** from checks 小橘 <xiaoju@shazhou.work>
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
|
||||
"files": {
|
||||
"ignore": ["**/dist/**"]
|
||||
},
|
||||
"organizeImports": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
@@ -35,17 +35,17 @@ describe("parseNerveConfig", () => {
|
||||
expect(result.ok).toBe(true);
|
||||
if (!result.ok) return;
|
||||
|
||||
expect(result.value.senses.cpu).toEqual({ group: "system", throttle: "5s", timeout: null });
|
||||
expect(result.value.senses.cpu).toEqual({ group: "system", throttle: 5000, timeout: null });
|
||||
expect(result.value.senses.memory).toEqual({
|
||||
group: "system",
|
||||
throttle: null,
|
||||
timeout: "10s",
|
||||
timeout: 10_000,
|
||||
});
|
||||
expect(result.value.reflexes).toHaveLength(3);
|
||||
expect(result.value.reflexes[0]).toEqual({
|
||||
kind: "sense",
|
||||
sense: "cpu",
|
||||
interval: "30s",
|
||||
interval: 30_000,
|
||||
on: null,
|
||||
});
|
||||
expect(result.value.reflexes[1]).toEqual({
|
||||
|
||||
@@ -4,24 +4,38 @@ import type { Result } from "./result.js";
|
||||
import { err, ok } from "./result.js";
|
||||
import type { NerveConfig, ReflexConfig, SenseConfig, WorkflowConfig } from "./types.js";
|
||||
|
||||
const DURATION_RE = /^\d+[smh]$/;
|
||||
const DURATION_RE = /^(\d+)([smh])$/;
|
||||
|
||||
function isValidDuration(value: string): boolean {
|
||||
return DURATION_RE.test(value);
|
||||
const DURATION_MULTIPLIERS: Record<string, number> = {
|
||||
s: 1_000,
|
||||
m: 60_000,
|
||||
h: 3_600_000,
|
||||
};
|
||||
|
||||
function parseDurationToMs(value: string): number | null {
|
||||
const match = DURATION_RE.exec(value);
|
||||
if (!match) return null;
|
||||
return Number(match[1]) * DURATION_MULTIPLIERS[match[2]];
|
||||
}
|
||||
|
||||
function isValidGroupName(value: string): boolean {
|
||||
return /^[a-zA-Z0-9_-]+$/.test(value);
|
||||
}
|
||||
|
||||
function parseDurationField(field: unknown, label: string): Result<string | null> {
|
||||
function parseDurationField(field: unknown, label: string): Result<number | null> {
|
||||
if (field === undefined || field === null) return ok(null);
|
||||
if (typeof field !== "string" || !isValidDuration(field)) {
|
||||
if (typeof field !== "string") {
|
||||
return err(
|
||||
new Error(`${label}: invalid duration "${field}" (expected e.g. "5s", "10m", "1h")`),
|
||||
);
|
||||
}
|
||||
return ok(field);
|
||||
const ms = parseDurationToMs(field);
|
||||
if (ms === null) {
|
||||
return err(
|
||||
new Error(`${label}: invalid duration "${field}" (expected e.g. "5s", "10m", "1h")`),
|
||||
);
|
||||
}
|
||||
return ok(ms);
|
||||
}
|
||||
|
||||
function validateSenseConfig(name: string, raw: unknown): Result<SenseConfig> {
|
||||
|
||||
@@ -7,14 +7,14 @@ export type Signal = {
|
||||
|
||||
export type SenseConfig = {
|
||||
group: string;
|
||||
throttle: string | null;
|
||||
timeout: string | null;
|
||||
throttle: number | null;
|
||||
timeout: number | null;
|
||||
};
|
||||
|
||||
export type SenseReflexConfig = {
|
||||
kind: "sense";
|
||||
sense: string;
|
||||
interval: string | null;
|
||||
interval: number | null;
|
||||
on: string[] | null;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user