-
Notifications
You must be signed in to change notification settings - Fork 1
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
Add type checking to items expression #69
Conversation
src/context.ts
Outdated
@@ -47,6 +48,43 @@ export interface DocumentTypeOption { | |||
}; | |||
} | |||
|
|||
export interface ServiceFetchConfiguration { |
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.
hrm, I'm not sure this belongs in the form-builder repository - does something break if you ignore serviceFetchConfiguration
in the VariableDefinition
type?
Perhaps it makes more sense to pass getInfernoLogicContext
via the builder context rather than providing the inputs and creating this context? That way we can build that context in our backend JS and pass it to the builder, and the open-forms specific stuff is more decoupled from the formio domain for the builder? Ultimately you sort of initialize the builder with "here, this is the infernologic type checking context, use that for your type checks and please validate the things in the builder" without the builder itself needing to understand what infer
needs (other than the function signature).
|
||
const NAME = 'openForms.itemsExpression'; | ||
|
||
const dataTypeForComponent = (component: AnyComponentSchema): JSONValue => { |
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.
would it make sense to add this to the infernologic
library itself? In a contrib/formio
package or something like that? That would also make it more easily shared between the builder & backend.
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.
The backend depends on the builder, even if the feature flag is off.
This failed build illustrates why this code lives here: https://github.com/open-formulieren/formio-builder/actions/runs/7101208159/job/19328836339?pr=69
The exhaustiveness checks for components that have been added since the version the PR was based on. CI telling us we should explicitly specify what type these form components expect 💚
... to item expression Closes open-formulieren/open-forms#3596 Closes open-formulieren/open-forms#3597
d33dd0f
to
9613441
Compare
@@ -1081,7 +1095,7 @@ export const SelectBoxes: Story = { | |||
isSensitiveData: false, | |||
openForms: { | |||
dataSrc: 'variable', | |||
itemsExpression: {var: 'someVar'}, | |||
itemsExpression: {var: 'current_year'}, // valid JSON, invalid expression |
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.
this makes the validation non-blocking, no? even if it's an invalid expression, it gets submitted and saved, that's what this assertion is doing. What's the reason for not preventing the <form>
submission?
} | ||
): JSONValue => { | ||
// For now return example values as accepted by InferNoLogic | ||
// But example values cannot distinguish arrays from tuples! |
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.
not even when using [...] as const
?
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.
Not sure what Chris and you meant here
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 think the issue is that some expressions like ['foo, 'bar']
get inferred as string[]
where-as they should be a two-tuple. If you define a fixed-length array of types, then it becomes a tuple in TS: https://www.typescriptlang.org/docs/handbook/basic-types.html#tuple
I was wondering if using the value as const
construct would make TS infer it as a tuple rather than an Array
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.
The problem is not TS, but open-formulieren/InferNoLogic/issues/5
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.
At some point the returntype of this function will have to become some form of type annotation. Not just to distinguish array
from tuple
, but also to distinguish string
from date
, datetime
etc.
checkbox: true, | ||
//@ts-ignore selectboxes always have component.defaultValue (this does work when rewritten as a lengthy switch/case) | ||
selectboxes: component.defaultValue, | ||
npFamilyMembers: {}, // TODO record type |
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.
this eventually becomes the same as selectboxes BUT it can also become a type: 'content'
component if there's an error 😬
9613441
to
9c8e830
Compare
9c8e830
to
b7135f8
Compare
@@ -46,6 +46,7 @@ const JSONEdit: React.FC<JSONEditProps & TextareaHTMLAttributes<HTMLTextAreaElem | |||
} | |||
|
|||
updateValue(updatedData); | |||
name && validateField(name); |
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.
@sergei-maertens we are hitting an issue here and don't know how to get things working:
name && validateField(name)
was added because the updateValue
call above did not trigger the validate
callback here (even though validateOnChange
is set to true
).
The issue is data gets out of sync, as here updatedData
corresponds to the latest version of the user input data, whereas adding a console.log
in the parent validate
callback shows an outdated value.
I've tried adding a call to the base Formik onChange
:
const {onChange: formikOnChange} = getFieldProps(name);
// Then calling `formikOnChange` in our custom `onChange`
But nothing works out
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 still don't think that wiring up this validate behaviour directly in the component is the right approach. Especially because this JSONEdit component is also used to edit the entire form component, but it could also point at a different subtree that has nothing to do with JSONLogic.
IMO hooking up the validator belongs in the zod validation schema, where you can make use of .refine
or .superRefine
to invoke this validator:
const schema = z.object({
itemsExpression: z.record(z.unknown()).superRefine(
... // in the callback here you'd call the `infer` validator/checker
),
});
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.
This is cleaner indeed. Unfortunately I seem to be facing robertLichtnow/zod-formik-adapter#15, will have to look closer.
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.
That seems weird since the (super)refine is used in the columns component validation. It could be that the error information is present, but just not displayed.
edit: hrm this might be why the validation errors are not shown onChange but only onBlur 🤔
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 see it being called with some logs, but the error doesn't seem to be displayed.
09a25e8
to
d672e94
Compare
8343b96
to
414a9b0
Compare
Sorry, postponing this :( |
Closes open-formulieren/open-forms#3596
Closes open-formulieren/open-forms#3597