diff --git a/nix-js/runtime-ts/src/conversion.ts b/nix-js/runtime-ts/src/conversion.ts index a83a429..e00b280 100644 --- a/nix-js/runtime-ts/src/conversion.ts +++ b/nix-js/runtime-ts/src/conversion.ts @@ -1,6 +1,7 @@ import { HAS_CONTEXT, NixStringContext } from "./string-context"; import { force } from "./thunk"; import type { NixValue } from "./types"; +import { isStringWithContext } from "./types"; export const nixValueToJson = ( value: NixValue, @@ -35,7 +36,6 @@ export const nixValueToJson = ( if (seen.has(v)) { throw new Error("derivation: circular reference detected in __structuredAttrs"); } - // FIXME: tryAttrsToString seen.add(v); } @@ -44,9 +44,31 @@ export const nixValueToJson = ( } if (typeof v === "object") { + if ("__toString" in v && typeof force(v.__toString) === "function") { + const toStringMethod = force(v.__toString) as (self: typeof v) => NixValue; + const result = force(toStringMethod(v)); + if (typeof result === "string") { + return result; + } + if (isStringWithContext(result)) { + if (outContext) { + for (const elem of result.context) { + outContext.add(elem); + } + } + return result.value; + } + return nixValueToJson(result, seen, outContext); + } + + if ("outPath" in v) { + return nixValueToJson(v.outPath, seen, outContext); + } + const result: Record = {}; - for (const [key, val] of Object.entries(v)) { - result[key] = nixValueToJson(val, seen, outContext); + const keys = Object.keys(v).sort(); + for (const key of keys) { + result[key] = nixValueToJson((v as Record)[key], seen, outContext); } return result; }