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

Add a plugin system #9

Closed
8 tasks done
ejpcmac opened this issue Oct 30, 2018 · 12 comments
Closed
8 tasks done

Add a plugin system #9

ejpcmac opened this issue Oct 30, 2018 · 12 comments
Assignees
Labels
T:Feature Type: Feature

Comments

@ejpcmac
Copy link
Owner

ejpcmac commented Oct 30, 2018

Steps

  • Start a toy project using TypedStruct and a plugin-to-be
  • Find a plugin idea
  • Start the plugin project
  • Define the plugin API and try concepts (try Plugin system #12)
  • Merge Plugin system #12
  • Adapt to the final v0.2.0 API while trying the implementation
  • Write documentation
  • Write tests

Rationale

Structs are used to represent many things in Elixir. Other libraries sometimes provide their own macros to define special functions alongside the struct. While integrating them with TypedStruct could sometimes be handy, there are two main issues:

  1. there is potentially a large number of libraries to integrate and maintain compatibility with,
  2. it would add code to TypedStruct that would be use by only a restricted number of projects.

There are already features request for Ecto (#7) and lens libraries (#8). More could come, so I think a plugin system would be a better solution. While I do not see currently how it would fit for the Ecto case, simpler cases like defining special functions from the struct fields could be handled by a function:

defmodule MyStruct do
  use TypedStruct

  # This would contain the define_lenses/? function.
  # Its parameters and return type are yet to define.
  import LensPlugin

  typedstruct do
    plugin :define_lenses

    field :name, String.t()
    field :age, integer(), some: :option
  end
end

Plugin functions would be called after the fields have been processed, with any option like some: :option made available to it. The complete API is to define, but here is a first idea. It could be interesting to provide some helpers for users to define their own top-level macros to replace typedstruct or extending it. Integration with Ecto could be explored in such a way.

API definition

In its PR #12, @uberbrodt defines the plugin API as a behaviour. This seems to be a good start.

Plugin definition

A TypedStruct plugin is a module that implements the TypedStruct.Plugin behaviour. This behaviour is made of several callbacks, all optional to let some flexibility to the user:

  • @macrocallback init(opts): lets the user inject some code in the module before the fields are processed. This can be used to register attributes or adding new macros in the scope.
  • @callback field(name, type, opts): called on each field, after it has been processed by TypedStruct.
  • @callback after_fields(opts): called after the fields, but before the struct and type definition.

Plugin usage

defmodule MyStruct do
  use TypedStruct

  typedstruct do
    plugin FirstPlugin
    plugin WithOptions, some: :option, another: "option"

    field :name, String.t()
    field :age, integer(), some: :option
  end
end

Options passed to the plugins are passed to the callbacks. The field/4 callbacks gets both the field-specific options and the plugin general option in its opts keyword.

@ejpcmac ejpcmac added the T:Feature Type: Feature label Oct 30, 2018
@ejpcmac ejpcmac self-assigned this Oct 30, 2018
@uberbrodt uberbrodt mentioned this issue Mar 10, 2019
@uberbrodt
Copy link
Contributor

I'm nearing v1.0 on my project that uses the provisional typed_struct plugin system. I thought it might be helpful to see how I use it, while you're writing the official plugin system: https://github.com/uberbrodt/ex_constructor

@ejpcmac
Copy link
Owner Author

ejpcmac commented Aug 3, 2019 via email

@ejpcmac
Copy link
Owner Author

ejpcmac commented Aug 4, 2019

I’ve just pushed 9b804d0 which contains the code for the pre-final version of the plugin API. It should be pretty stable now, except if some flaw is found.

I’ve removed the tests since they don’t match anymore, and there is currently no documentation.

@uberbrodt By reading the code, you should be able to adapt your plugin fairly easily. The main difference about the field/3 callback is that it must return a quoted expression. It’s a function, but think about it like a macro that can inject additional code on each call of the TypedStruct.field/2,3 macro. Provided that I needed to call dynamically this callback on each field for each plugin, I couldn’t use a “real” macro and learned about Module.eval_quoted/2 which did the trick.

@avitex
Copy link

avitex commented Mar 30, 2020

Just a friendly bump. Any ETA on this? :)

@ejpcmac
Copy link
Owner Author

ejpcmac commented Mar 30, 2020

@avitex I’m currently hard-working to free some time to get back on it soon.

Between August and November, I’ve been busy preparing my trip to Kerguelen Islands. In November I’ve been able to work a tiny bit on the documentation while at sea on the Marion Dufresne, but since my arrival in Kerguelen I’ve spent nearly all my spare time on writing about my experience there—I quite expected that, but not to that point.

My ETA on getting back to software development projects is around April 15-20th. TypedStruct 0.2.0 is number 1 on my list.

@avitex
Copy link

avitex commented Mar 30, 2020

@ejpcmac Thanks for the speedy reply. Life just has a habit of rearranging priorities all the time. Stay safe out there!

@ejpcmac
Copy link
Owner Author

ejpcmac commented Mar 30, 2020

Life just has a habit of rearranging priorities all the time.

Well said @avitex! Since I’m a bit carving software development—I’m doing mostly sysadim here—be sure it is currently rising on my general priority list. It will be good to ship a new version and start working on new projects :)

@ejpcmac
Copy link
Owner Author

ejpcmac commented Apr 19, 2020

Hello all! I have some good news: I’m back on it starting today! I won’t be able to be 100% on it in my spare time so don’t expect something in two days, but I hope to release TypedStruct 0.2.0 around mid-May.

@avitex
Copy link

avitex commented Apr 20, 2020

Awesome news :)

@ejpcmac
Copy link
Owner Author

ejpcmac commented Apr 27, 2020

I’ve just published the documentation on develop if you want to give it a try.

@avitex
Copy link

avitex commented Apr 27, 2020

Will have a look today, thanks :)

@ejpcmac
Copy link
Owner Author

ejpcmac commented May 16, 2020

Quick ETA update : I’ve been busy again the past two weeks, not being able to work on TypedStruct at all. I’m on the field without my computer next week, but I have managed to free my schedule enough to start working on TypedStruct back on Monday 25th. It should be OK before mid-June then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T:Feature Type: Feature
Projects
Status: Solved
Development

No branches or pull requests

3 participants