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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supported nested fields #1621

Closed
wants to merge 27 commits into from
Closed

Supported nested fields #1621

wants to merge 27 commits into from

Conversation

Ben-Ho
Copy link
Contributor

@Ben-Ho Ben-Ho commented Jan 25, 2024

No description provided.


type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...0[]];
type Join<K, P> = K extends string | number ? (P extends string | number ? `${K}${"" extends P ? "" : "."}${P}` : never) : never;
export type DeepKeyOf<T, D extends number = 10> = [D] extends [never]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fancy. Why does the first, commented out, version not work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because it throws an error for a recursive structure like in the demo project. This is handled with Prev-Type.

I also tried to replace Prev and Join with the same-named Types of ts-toolbelt but they behave differently. And I'm actually not so experienced with typescript to find a library-supported solution in an reasonable amount of time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typing is now solved 👍

.replace(/: true,/g, "")
.replace(/: true/g, "")
.replace(/"/g, "")
.replace(/:/g, "");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, you are messing with the JSON output string, wouldn't a recursive function be relatively easy to implement?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's right. but I wanted to return nice indentations and json is somewhat similar. I didn't check, but is the code-format done with some prettier command-call? As I saw no "ugly" code. So indentations are probably not even needed, and a flat string would be much easier generated so I could change this json-messing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please try it out. (adding an indentation level to the recursion also doesn't sound too complicated)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. changed it to recursive function

@@ -16,13 +17,12 @@ export function generateForm(
const gqlQueries: Record<string, string> = {};
const imports: Imports = [];

const fieldNamesFromConfig = config.fields.map<string>((field) => field.name);
Copy link
Contributor Author

@Ben-Ho Ben-Ho Jan 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@johnnyomair solved it by adding <string>. Hovering over field.name said type is string. so this was probably some typescript bug.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand your comment :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

regarding the question in slack, how I should fix the typescript issue with recommended refactor using for...of instead of map vs ts-ignore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is also solved 👍

@@ -58,6 +58,8 @@ export function generateForm(
\${${`${instanceGqlType}FormFragment`}}
`;

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore TS2589: Type instantiation is excessively deep and possibly infinite.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this hint is true, as we use recursion to create fields. but this is required. I didn't look up a different solution or a workaround for this typescript-error.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not a hint, its an error :)

And it says the types are recursive (not the runtime code) which you should avoid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright, then I will look into it 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved 👍

@@ -17,7 +18,7 @@ export type FormFieldConfig<T> = (
| { type: "staticSelect"; values?: string[] }
| { type: "asyncSelect"; values?: string[] }
| { type: "block"; block: BlockReference }
) & { name: keyof T; label?: string; required?: boolean };
) & { name: Leaves<T> | Paths<T>; label?: string; required?: boolean };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs more explanation

  • what is Leaves and Paths, why do we need both?
  • and: we really, really need a demo using this
    • there are already a few nested objects for product type
    • please do yourself and everyone else a favor and develop using demo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I faced the problem with the demo-code when I was moving my implementation. (in my specific project the commented-out version did work, as there was no recursion or block-structure)

I tried to support this:

Entity: {
    foo: string;
    address: {
        city: string;
        zip: string;
    };
    block: {
        .... some properties
    }
}

const formConfig: {
    fields: [
        { name: "foo", ...},
        { name: "address.zip", ...}
        { name: "block", ... }
    ]
}

Leaves only supports "foo", "address.zip", "block.some_property"
Paths only supports "foo", "address", "block"

so I combined those two. I'll add an example for name: "packageDimensions.height" as this is the only case missing.

Would you say this is something that requires a comment next to Leaves | Paths ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you need Paths? packageDimensions is not a possible value, only packageDimensions.height is

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because of properties like image-block and probably special form-fields supporting other object-structures. (but there may be other solutions like defining multiple properties, e.g. Pick/ShowCoordinates-Field need to set {type: "coordinates", longitude: "place.lng", latitude: "place.lat"} instead of {type: "coordinates", name: "place"}

Copy link
Contributor Author

@Ben-Ho Ben-Ho Jan 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also thought of make this configurable with separate generic parameter FormConfig<T, ObjectFields>

const type MyConfig = FormConfig<Product, "image" | "place">;

but I don't know how to implement this kind of typing-behaviour and another reason: if, as the developer, I'm required to define the special fields, it shouldn't be to much of a problem to just don't use them in the first place.

better typing is probably helpful if my entity is changed afterwards. but to support this we might need some way to detect, at least for now, any block-type.

Base automatically changed from admin-gen-configurable to next February 12, 2024 11:37
@Ben-Ho
Copy link
Contributor Author

Ben-Ho commented Feb 12, 2024

@nsams I think this pull-request is ready now. It works as expected.

image

@Ben-Ho
Copy link
Contributor Author

Ben-Ho commented Feb 13, 2024

closed because of #1695

@Ben-Ho Ben-Ho closed this Feb 13, 2024
@Ben-Ho Ben-Ho deleted the benji-admin-generator branch February 13, 2024 15:12
@Ben-Ho Ben-Ho restored the benji-admin-generator branch February 15, 2024 14:53
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

Successfully merging this pull request may close these issues.

2 participants