Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

JsonSchema to SureType conversion loses validation information #16

Open
hborchardt opened this issue Nov 5, 2021 · 1 comment
Open

Comments

@hborchardt
Copy link

Hi! 馃憢 Thanks again for typeconv!

I was trying to convert a json schema to suretype and noticed that the "minimum" and "maximum" properties for numbers are not honored in the generated schema.

Digging deeper it seems that code for this is in place, but typeconv chooses to convert jsc to ct to st, even though a shortcut from jsc to st is available (defined in the st writer). In this process, the minimum and maximum information gets lost. On a sidenote, the ct to st conversion actually generates a json schema based on the ct representation, and converts that to suretype. I confirmed that this intermediate json schema does not contain the minimum and maximum information.

One could argue that this validation information should also be present in the core-types representation, so that the conversion from jsc to ct should not be lossy. However, I did not look down that path and focused on the following:

The logic for finding the best conversion path in format-graph.ts, while considering shortcuts, does not work optimally if a format can be directly connected to the writer.

I was able to solve this problem by postulating that every reader has a trivial shortcut to itself (so in my case, "jsc to jsc"), which can then be connected with the "jsc to st" shortcut on the st writer side.

Here is the diff that solved my problem:

diff --git a/node_modules/typeconv/dist/converter.js b/node_modules/typeconv/dist/converter.js
index 0c6e981..21c7964 100644
--- a/node_modules/typeconv/dist/converter.js
+++ b/node_modules/typeconv/dist/converter.js
@@ -27,7 +27,9 @@ async function convertAny(data, reader, writer, format, readOpts, writeOpts) {
         };
     }
     else {
-        const read = await reader.shortcut[format](data, readOpts);
+        const read = reader.kind === format
+          ? { data: data, convertedTypes: [], notConvertedTypes: [] }
+          : await reader.shortcut[format](data, readOpts);
         const written = await writer.shortcut[format](read.data, writeOpts, reader);
         return {
             output: written.data,
diff --git a/node_modules/typeconv/dist/format-graph.js b/node_modules/typeconv/dist/format-graph.js
index 12669ba..85a00d2 100644
--- a/node_modules/typeconv/dist/format-graph.js
+++ b/node_modules/typeconv/dist/format-graph.js
@@ -51,7 +51,7 @@ class FormatGraph {
                 paths.set(pathKey, newPath);
             };
             const formats = [
-                ...shortcuts ? [] : ['ct'],
+                ...shortcuts ? [reader.kind] : ['ct'],
                 ...shortcuts !== false
                     ? Object.keys((_a = reader.shortcut) !== null && _a !== void 0 ? _a : {})
                     : []

This issue body was partially generated by patch-package.

@gCardinal
Copy link

gCardinal commented Dec 8, 2021

+1. Losing validation information is a big loss.

Note that the above solution only partially worked for me; I have some uuid strings and ajv apparently does not have a .format('uuid'). At least not the version installed when installing typeconv. It also complained when a .pattern("^[A-Z]+") was generated.

export const schemaEventSessionEgmActiveV1 = suretype({
    name: "EventSessionEgmActiveV1"
}, v.object({
    eventHeader: annotate({
        title: "Enterprise Event Header Model - V1",
        description: "A quick test of a model and it's generated interface."
    }, v.object({
        originatorUUID: annotate({
            title: "originatorId",
            description: "Lorem ipsum dolor sit amet."
        }, v.string().pattern("^[A-Z]+").format("uuid").required()),
    }).additional(true).required()),
}).additional(true));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants