From 7a0665da6d7b992b78291c44bf1b4dfc2bb9b4f0 Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Tue, 20 May 2025 15:48:28 +0200 Subject: [PATCH] Feat(jsonschema): convert deferredModule to unknown --- lib/jsonschema/default.nix | 11 ++++++++ .../clan_cli/tests/test_deserializers.py | 28 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/lib/jsonschema/default.nix b/lib/jsonschema/default.nix index b0bad30de..094407869 100644 --- a/lib/jsonschema/default.nix +++ b/lib/jsonschema/default.nix @@ -304,6 +304,17 @@ rec { # return jsonschema property definition for raw then exposedModuleInfo // default // example // description // { type = allBasicTypes; } + else if + # This is a special case for the deferred clan.service 'settings', we assume it is JSON serializable + # To get the type of a Deferred modules we need to know the interface of the place where it is evaluated. + # i.e. in case of a clan.service this is the interface of the service which dynamically changes depending on the service + # We assign "type" = [] + # This means any value is valid — or like TypeScript’s unknown. + # We can assign the type later, when we know the exact interface. + # tsType = "unknown" is a type that we preload for json2ts, such that it gets the correct type in typescript + (option.type.name == "deferredModule") + then + exposedModuleInfo // default // example // description // { tsType = "unknown"; } # parse enum else if option.type.name == "enum" diff --git a/pkgs/clan-cli/clan_cli/tests/test_deserializers.py b/pkgs/clan-cli/clan_cli/tests/test_deserializers.py index 0bc64d0fd..58b24c36b 100644 --- a/pkgs/clan-cli/clan_cli/tests/test_deserializers.py +++ b/pkgs/clan-cli/clan_cli/tests/test_deserializers.py @@ -294,3 +294,31 @@ def test_enum_roundtrip() -> None: assert from_dict(Person, data2) == expected2 assert dataclass_to_dict(expected2) == data2 + + +# for the test below +# we would import this from the nix_models +class Unknown: + pass + + +def test_unknown_deserialize() -> None: + @dataclass + class Person: + name: Unknown + + data = {"name": ["a", "b"]} + + person = from_dict(Person, data) + person.name = ["a", "b"] + + +def test_unknown_serialize() -> None: + @dataclass + class Person: + name: Unknown + + data = Person(["a", "b"]) # type: ignore + + person = dataclass_to_dict(data) + assert person == {"name": ["a", "b"]}