-
Notifications
You must be signed in to change notification settings - Fork 6
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’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Recursive #29
Recursive #29
Conversation
29bccee
to
4a4daad
Compare
54264b4
to
d3becc9
Compare
6bb6316
to
fbfa1f9
Compare
Great, thanks. But would you mind checking once more? I wrap references now into a union if there are extra properties like
I did add a section to the README on use of JSON References and removed the old to-do. I didn't add a full "how to use" section though as the README doesn't really contain such a section on all of its properties. |
Just a heads up that after this Friday, I may be out of Internet contact for a few days (moving and in a foreign country). |
Hmm... I'm not sure if in my implementation this is the case or this was because of your recent changes but.... If you add the following in the last test scenario
Why is the profileContact no longer optional? and why did it become lazy? I can see that there's isOptional in the zerialize but it's lost on the dezerialize even with the json pointer.
And shouldn't it be directly just be a pointer like
|
02e04e3
to
d13582a
Compare
And if you want to test my |
@jadedevin13 : Nevermind, I think I've got a fix. Plan to report back as I am able. |
cce0959
to
05bc001
Compare
Ok, this should be ready for review again, @jadedevin13 . I disabled the reserialization check because it will add some unnecessary single-item unions--not sure that that can be avoided, and it still performs the same validation. |
Sorry my bad, I was thinking more of something like this.
i think we should've added a type of lazy in zerializers to aid this and those that are lazy are the only ones who'll have refs
|
That would be convenient to allow, but when dezerializing, I don't know what to place for the
Not sure what you mean here, but in any case, I think we have to add our own lazy placeholders in dezerialize in order to successfully replace all references, and there is no way in the current Zod API that I can tell which allows swapping a placeholder like ZodLazy with something else after the fact. |
bd96acf
to
e44519b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks you two for duking it out! I trust you two on this one, I just gave it a surface-y skim and it looks mostly good and mergeable to me.
src/index.test.ts
Outdated
] as const)("zerialize %#", (schema, shape) => { | ||
expect(zerialize(schema)).toEqual(shape); | ||
const zer = zerialize(schema); | ||
// console.log(JSON.stringify(zer, null, 2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
leftover comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, fixed.
README.md
Outdated
to use a library like [`json-refs`](https://github.com/whitlockjc/json-refs) | ||
(with `resolveRefs`) to first resolve such references and then supply the object | ||
to `dezerialize`. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is that still the case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's still the case. Btw, I added another JSON refs caveat on the README.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify further...one must use an external JSON refs library to resolve things like:
{"$ref": "https://example.com/some/Zodex/JSON/file.json"}
or
{"$ref": "/a/Zodex/JSON/file/at/root.json"}
but not for internal references like:
{"$ref": "#/somewhere/in/the/document"}
Also: - update erring pnpm actions script
src/zerialize.ts
Outdated
ZodIntersection: (def, opts) => { | ||
opts.currentPath.push("left"); | ||
const left = s(def.left, opts); | ||
opts.currentPath.pop(); | ||
|
||
opts.currentPath.push("right"); | ||
const right = s(def.right, opts); | ||
opts.currentPath.pop(); | ||
|
||
return { | ||
type: "intersection", | ||
left, | ||
right, | ||
}; | ||
}, | ||
|
||
ZodFunction: (def, opts) => { | ||
opts.currentPath.push("args"); | ||
const args = s(def.args, opts); | ||
opts.currentPath.pop(); | ||
|
||
opts.currentPath.push("returns"); | ||
const returns = s(def.returns, opts); | ||
opts.currentPath.pop(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer all of theses instances of parameter mutation to be replaced by constructing new.
e.g.:
ZodIntersection: (def, opts) => ({
type: "intersection",
left: s(def.left, { ...opts, currentPath: [...opts.currentPath, "left"] }),
right: s(def.right, {
...opts,
currentPath: [...opts.currentPath, "right"],
}),
}),
imo it makes for more readable, less error prone code. I think the mutative style can make sense for performance, but I don't think that's a chief concern here?!
Thinking about it more, I'm kind of surprised this is even working at all, given that (the way I'm reading this code) is that within a zerialize run all fns share the same reference to a currentPath
array that's mutated all over the place
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've dropped the mutative style. I think the former style worked because it was meticulous in reverting the changes and each step would eventually return, but in any case this works also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also added a commit to revert back to the terser style of using arrow functions without return statements. I personally find that style cumbersome in debugging and refactoring, but I added the commit if you really do prefer it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've dropped the mutative style. I think the former style worked because it was meticulous in reverting the changes and each step would eventually return, but in any case this works also.
It did look meticulous in that way, I did not mean to doubt that.
Yet the reference to the array that was passed in, is also the one that was mutated thereafter. So if anything with the s=>zerializeRefs
call were to use or mutate the ref at a later point, wouldn't this cause the spooky distance action that I fear?
I also added a commit to revert back to the terser style of using arrow functions without return statements. I personally find that style cumbersome in debugging and refactoring, but I added the commit if you really do prefer it.
While I do agree that debugging takes more steps, I prefer optimizing for reading on code that is straightforward enough where I don't expect a ton of debugging sessions. So it's a bit of a subjective value judgment.
Though even if, thankfully VSCode added some helpful structural editing commands here: when your cursor is within a terse arrow fn, press Cmd + .
(aka "Quick Fix") and hit Enter
(on "Add braces to arrow function"). So it's only 3 keypresses to make it more debuggable which I find to be an okay cost
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re: arrow functions, sweet, thanks for the tip... Re: the mutating array, I'll admit it's hard to get my head around it. And thanks for the review!
Thankslots for your work you two! |
Recursive schemas via JSON References
feat: support recursive schemas
Closes #13.
Note that there is one (hopefully minor) API risk in that in order to modify schemas in place, I insert a
z.lazy()
as a placeholder and later modify its_def.getter
internal function to the desired getter. (This was necessary because I had to wait to iterate the whole structure so that each JSON path could be mapped and the JSON reference successfully resolved.)