ffMathy/FluffySpoon.JavaScript.CSharpToTypeScriptGenerator.Webpack

Adding "I" to class names

david-hollifield opened this issue · 10 comments

My config looks like this:

        poco(
            ".",
            [
                "../../Entities/*.cs"
            ],
            {
                defaults: {
                    classEmitOptions: {
                        perClassEmitOptions: (classObject) => {
                            name: "I" + classObject.name,
                            inheritedTypeEmitOptions: {
                                mapper: (type, suggested) => 'I' + suggested
                            }
                        }
                    },
                    enumEmitOptions: {
                        declare: false
                    },
                    propertyEmitOptions: {
                        perPropertyEmitOptions: (property) => {
                            name: property.name;
                        }
                    }
                },
                file: {

                }
            }
        )
    ]

webpack chokes on the perClassEmitOptions with:

webpack-typings.config.js:53 
                            inheritedTypeEmitOptions: {
                                                    ^
SyntaxError: Unexpected token :
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:616:28)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at requireConfig (\node_modules\webpack\bin\convert-argv.js:97:18)

Any ideas?

Is it a JavaScript or TypeScript file? Arrow-type EcmaScript functions are not yet supported by nodejs as far as I know.

Closing - will re-open if using general functions didn't fix the issue.

DOH! I'm an idiot ;). This is my current config:

plugins: [
        poco(
            ".",
            [
                //"Models/*.cs",
                "../../Entities/*.cs"
            ],
            {
                defaults: {
                    classEmitOptions: {
                        perClassEmitOptions: function (classObject) {
                            return {
                                name: "I" + classObject.name,
                                inheritedTypeEmitOptions: {
                                    mapper: function (type, suggested) {
                                        return 'I' + suggested;
                                    }
                                }
                            }
                        }
                    },
                    enumEmitOptions: {
                        declare: false
                    },
                    propertyEmitOptions: {
                        perPropertyEmitOptions: function (property) {
                            return {
                                name: property.name
                            };
                        }
                    }
                },
                file: {

                }
            }
        )
    ]

Unfortunately, it's now showing a different issue:

declare namespace PhotoFinale {
    namespace Api {
        namespace Entities {
            enum PaymentOptions {
                None = -1,
                CreditCard,
                PayPal = 1,
                PayInStore = 2,
                StoreAccountCard = 3,
                AccountCredit = 4
            }
            interface IPaymentInfo {
                PaymentCard: PaymentCard;
                PaymentOption: PaymentOptions;
                RequiresPayment: boolean;
            }
            interface IPaymentCard {
                AccountNumber: string;
                Amount: number;
                Ccv: string;
                ExpirationMonth: number;
                ExpirationYear: number;
                PaymentMethodId: number;
            }
        }
    }
}

Notice how the type in IPaymentInfo is still PaymentCard instead of IPaymentCard. Am I missing a config option?

Within your defaults in the perPropertyEmitOptions in addition to a name property, set some typeEmitOptions which then have some perTypeEmitOptions which then set their name properties.

Does that make sense?

Yeah, makes sense. I tried that and am trying to figure out how to determine if the "type" passed into the mapper is one of my classes or something else like string or number. Here's what I have:

                    typeEmitOptions: {
                        mapper: function (type, suggested) {
                            if (type.namespace) {
                                console.log(type.namespace.fullName);
                            }
                            if (type.fullName.startsWith("PhotoFinale")) {
                                return 'I' + suggested;
                            } else {
                                return suggested;
                            }
                        }
                    }

Unfortunately, none of the types have a namespace.

What does the c sharp file look like?

Here's a sample of one:

using System;

namespace PhotoFinale.Api.Entities
{
    public enum PaymentOptions
    {
        None = -1,
        CreditCard = 0,
        PayPal = 1,
        PayInStore = 2,
        StoreAccountCard = 3,
        AccountCredit = 4
    }

    public class PaymentInfo
    {
        public PaymentInfo()
        {
            PaymentOption = PaymentOptions.None;
        }

        public PaymentCard PaymentCard { get; set; }
        public PaymentOptions PaymentOption { get; set; }
        public bool RequiresPayment { get; set; }
    }

    public class PaymentCard
    {
        public PaymentCard()
        {
            PaymentMethodId = -1;
            AccountNumber = string.Empty;
            Ccv = string.Empty;
            Amount = 0.0M;
            ExpirationMonth = DateTime.Now.Month;
            ExpirationYear = DateTime.Now.Year;
        }

        public string AccountNumber { get; set; }
        public decimal Amount { get; set; }
        public string Ccv { get; set; }
        public int ExpirationMonth { get; set; }
        public int ExpirationYear { get; set; }
        public int PaymentMethodId { get; set; }
    }
}

And the d.ts

declare namespace PhotoFinale {
    namespace Api {
        namespace Entities {
            enum PaymentOptions {
                None = -1,
                CreditCard,
                PayPal = 1,
                PayInStore = 2,
                StoreAccountCard = 3,
                AccountCredit = 4
            }
            interface IPaymentInfo {
                PaymentCard: PaymentCard;
                PaymentOption: PaymentOptions;
                RequiresPayment: boolean;
            }
            interface IPaymentCard {
                AccountNumber: string;
                Amount: number;
                Ccv: string;
                ExpirationMonth: number;
                ExpirationYear: number;
                PaymentMethodId: number;
            }
        }
    }
}

I'm just trying to get the "I"+name to work for now. I'll also need to filter out enums during my mapping for my final pass.

What output do you get when you emit the type? It should have a full name space actually. It's name should be for instance PaymentCard.

This is what I'm being passed as type to typeEmitOptions.mapper() for PhotoFinale.Api.Entities.PaymentInfo:

{"name":"PaymentCard","genericParameters":[],"isNullable":false,"namespace":null}
{"name":"PaymentOptions","genericParameters":[],"isNullable":false,"namespace":null}
{"name":"bool","genericParameters":[],"isNullable":false,"namespace":null}
{"name":"string","genericParameters":[],"isNullable":false,"namespace":null}
{"name":"decimal","genericParameters":[],"isNullable":false,"namespace":null}
{"name":"string","genericParameters":[],"isNullable":false,"namespace":null}
{"name":"int","genericParameters":[],"isNullable":false,"namespace":null}
{"name":"int","genericParameters":[],"isNullable":false,"namespace":null}
{"name":"int","genericParameters":[],"isNullable":false,"namespace":null}

I was hoping I could use the namespace and there would be some type of indicator if something was an enum. Then I could add the "I" to PaymentCard, but not PaymentOptions.

Unfortunately that is not currently possible. The TypeScript parser currently being used is based on parsing C# code syntactically, but not semantically. It doesn't have a chance of knowing what namespace those types belong to.

However, what we could do is provide an array with potential namespaces. Then based on that, perhaps we could map the type to a reference that it has passed before. I am leaving this issue open to implement that next.

Alternatively now what you can do is add the onAfterParse callback and there check all classes and enums of the file and find the matching one. See the angular recipes for an example. Does that make sense?