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

Plan client model/class generators #77

Closed
nilslice opened this issue Feb 21, 2017 · 6 comments
Closed

Plan client model/class generators #77

nilslice opened this issue Feb 21, 2017 · 6 comments

Comments

@nilslice
Copy link
Contributor

I would like to start a discussion to plan a way to easily generate client models or classes which interact with Ponzu server content API endpoints, keeping an extensible design in mind so that multiple languages can be added.

Either building upon @natdm's typewriter package or implementing something ponzu-specific for generating client code in various languages including Go, Swift/ObjC, Java, JS, etc. Also, @bketelsen's ponzigen is a good example of making clients to interact with Ponzu from the outside.

My initial thoughts for the command line API would be similar to the content type generator:

$ ponzu gen model:js review
# or, to generate multiple client models in one pass:
$ ponzu gen model:js,go,swift review

Here is a gist with some example client code and other files for people to suggest code in other languages: https://gist.github.com/nilslice/297ce9d7eb18c58bab375f0844f4cd19

/cc @natdm @briandowns @bketelsen

All feedback is welcome & appreciated. Thank you!

@natdm
Copy link

natdm commented Feb 21, 2017

To be clear, this is parsing types that was already generated by ponzu? Not being generated at the same time?

@nilslice
Copy link
Contributor Author

Right - the thought is that once you've set your content types, you then generate the client models.

If possible to do cleanly, I think the generated client models should be mostly left alone from a file editing standpoint. This way you can rerun the model generator over and over after Ponzu content types are updated, just like typewriter.

@natdm
Copy link

natdm commented Feb 22, 2017

I think the first thing I'd like to try is to look at Typewriter and see what needs to be done for that engine to be used by Ponzu, and what changes need to be made there. I don't predict too many.

Currently this is how Typewriter works.

It parses all types and creates a new model for each one:

// PackageType is a package-level type. Any package type will
// be templated with a full type creation statement and possibly a comment
type PackageType struct {
	Name    string    // Name of the type
	Comment string    // Any comment that type may have
	Type    Templater // The templater that draws the code, switching it up per language
	Tag     string    // any json/tw tags
}
// Templater interface is able to write a template to a writer, based on a Language
type Templater interface {
	Template(w io.Writer, lang Language) error
}

And then they all get parsed in alphabetical order, through a template (or more, depending on the type).

The templates look like this:

var tsTemplates = map[templateKey]string{
	header: `// Automatically generated by typewriter. Do not edit.
// http://www.github.com/natdm/typewriter

`,
	arrayOpen:  `Array<`,
	arrayClose: `>`,
	basic:      `{{if .Pointer}}?{{end}}{{updateTSType .Type}}`,
	comment:    `{{tsComment .Comment}}`,
	declaration: `
{{tsTypeComment .Comment}}type {{.Name}} = `,
	fieldClose: `, `,
	fieldName: `
	{{.Name}}: `,
	mapClose:    ` }`,
	mapKey:      `{ [key: `,
	mapValue:    `]: `,
	structClose: `}`,
	structOpen:  `{`,
}

What languages do you think you want these Go types parsed to, in order of priority? And the more 100% complete examples you can give, the better. Some issues I bump in to are things like embedded types (where I now just get the fields from the embedded type and insert them in the Struct, since the goal was JS/TS/Flow/Elm and they don't really do embedded types) and types in other packages. eg: type x map[string]item.Item. I then have to look at where the 'item' package is, get that type put it in the models to be generated, then use that instead (work in progress). So...

type x map[string]item.Item

turns in to

// replaced dot with underscore to help avoid other collisions with a possible 'Item' type already created
export type item_Item = {
    ...
}
export type x = { [key: string]: item_Item }

@nilslice
Copy link
Contributor Author

@natdm -

Apologies for the delay here.. I have a fast-approaching deadline for a project at the moment. In fact, I'm building a semi-complex javascript UI over Ponzu data, so I'm getting some helpful experience on what would be useful here.

It turns out, I don't feel that doing as much code generation on the front end will be particularly useful after all. The only part I think we could reliably generate that would be useful is that which is done by typewriter.. keep the client models in sync as the types change.

The other HTTP stuff is too preference-based to really be beneficial, i.e. people use jQuery Ajax, or superagent, request, etc... and several other libraries across the mobile landscape.

In my own project, I only have 4 data types, and relative to the rest of the project, there is very little code written to manage the HTTP interaction with Ponzu's content API. I think it might be better to let this be an external decision for the time being, instead of something built directly into Ponzu. Maybe we could mention the typewriter project in the wiki or something so others are more inclined to write and share templates for other languages.

What do you think?


As for your comments -- I think the engine is already there for JS (and maybe even HTML) code gen. The embedded type issue isn't typically a problem for Ponzu content types, since the only type we really embed is an item.Item & the find-and-insert approach works fine.

@natdm
Copy link

natdm commented Feb 23, 2017

That sounds great. A mention is fine with me! If you are using it and have an issue, please create an issue in Typewriter.

@nilslice
Copy link
Contributor Author

Ok, I will close this issue for now, but add some label so it doesn't get lost. I want to revisit this later and see how we can continue to make the dev experience better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants