feat(web): complete product workflow implementation
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-09-06 08:33:27 +08:00
parent 7e3f6da78b
commit 1184a51ddf
39 changed files with 3736 additions and 160 deletions

View File

@@ -9,6 +9,36 @@ function fnv1a(value: string): number {
return hash >>> 0;
}
export type ModifierParameterMetadata = {
key: string;
value: unknown;
kind: "boolean" | "number" | "string" | "enum" | "object";
options?: string[];
};
/** Derives editable fields from the metadata carried by the authoritative modifier IR. */
export function modifierParameterMetadata(modifier: ModifierIR): ModifierParameterMetadata[] {
return Object.entries(modifier.parameters ?? {}).map(([key, rawValue]) => {
// Main may carry a descriptor when RNA exposes enum choices alongside the
// current value. Keep the descriptor opaque to callers while deriving the
// editable value and choices from it.
const descriptor = rawValue && typeof rawValue === "object" && !Array.isArray(rawValue) &&
"value" in rawValue && ("kind" in rawValue || "options" in rawValue)
? rawValue as { value: unknown; kind?: ModifierParameterMetadata["kind"]; options?: unknown[] }
: undefined;
const rawOptions = descriptor?.options ?? (Array.isArray(rawValue) && rawValue.every((entry) => typeof entry === "string") ? rawValue : undefined);
const options = rawOptions?.map(String);
const value = descriptor?.value ?? (options ? options[0] : rawValue);
const kind = descriptor?.kind ?? (
typeof value === "boolean" ? "boolean" :
typeof value === "number" ? "number" :
typeof value === "string" ? (options ? "enum" : "string") :
"object"
);
return { key, value, kind, options: options ?? undefined };
});
}
/** Hashes evaluated modifier identity/state, excluding display timestamps. */
export function modifierStackHash(stack: readonly ModifierIR[] | undefined): string {
const canonical = (stack ?? []).map((modifier) => ({