aws-cloudformation / cloudformation-cli-typescript-plugin

The CloudFormation Provider Development Toolkit Node.js Plugin allows you to autogenerate TypeScript code based on an input schema.
Apache License 2.0
45 stars 15 forks source link

Resource model break when specifying an array with unique: true #97

Open rene84 opened 1 year ago

rene84 commented 1 year ago

I've noticed when specifying an array with unique: true translates the model into a Set instead of an Array (makes sense)

but then when passing an actual array as example input, the resource provider fails. Consider for example:

        "Tags": {
            "type": "array",
            "maxItems": 50,
            "uniqueItems": true,
            "insertionOrder": false,
            "description": "An array of key-value pairs to apply to this resource.",
            "items": {
                "$ref": "#/definitions/Tag"
            }
        },

with input:

"Tags": [{
            "Key": "name",
            "Value": "value"
        }]

gives error

"message": "Error: Error: Unsupported type: object [Tag] for tags (Error)",

Removing the uniqueItems fixes the issue and the main thing I notice is that in the generated code the type changes from a Set to an Array

eduardomourar commented 1 year ago

I think this is related to some issues in the class-transformer library. Maybe those workarounds are relevant: https://github.com/typestack/class-transformer/issues/288#issuecomment-614754298 and https://github.com/typestack/class-transformer/issues/495#issuecomment-756449822.

Could you post an snippet of your models.ts file? I believe you can modify your generated models.ts with the provided workaround in order to figure out which change has to be made to the TypeScript code generator.

rene84 commented 1 year ago

Sure. It looks like this:

    @Expose({ name: 'Tags' })
    @Transform(
        (value: any, obj: any) =>
            transformValue(Tag, 'tags', value, obj, [Set]),
        {
            toClassOnly: true,
        }
    )
    tags?: Optional<Set<Tag>>;

With uniqueItems: false it looks like this

    @Expose({ name: 'Tags' })
    @Type(() => Tag)
    tags?: Optional<Array<Tag>>;
eduardomourar commented 1 year ago

You can find a test reproducing what you faced here.

eduardomourar commented 1 year ago

This has been fixed by https://github.com/aws-cloudformation/cloudformation-cli-typescript-plugin/pull/98.