digitallyinduced / ihp

🔥 The fastest way to build type safe web apps. IHP is a new batteries-included web framework optimized for longterm productivity and programmer happiness
https://ihp.digitallyinduced.com/
MIT License
4.87k stars 192 forks source link

Plugin API #562

Open mpscholten opened 3 years ago

mpscholten commented 3 years ago

Plugin Ideas:

We need a way for Plugins to be hooked into an IHP app.

Montmorency commented 3 years ago

Hey just put up a proto-type of an ihp style plugin I've factored out of an Bing maps app. The readme has some overall style ideas but the main points are:

1) you could write all the API logic for the plugin independently and then expose it with the same Application/Helper/Controller.hs and Application/Helper/View.hs type patterns which would make plugin use simpler for end user and allow plugin developers to have their library still flexible for other uses. In this pattern ihp-users would just have to look to see which convenience functions are exposed for their views and controllers and keep working.

2) The ihp nix formula could allow users to specify a list of plugins they want (from what I called a curry-house ;) and then those can be checked out into the nix store. This has additional advantage that nix would make it much simpler to keep all the plugins synchronized with IHP by specifying a nixpkgs image.

mpscholten commented 3 years ago

you could write all the API logic for the plugin independently and then expose it with the same Application/Helper/Controller.hs and Application/Helper/View.hs type patterns which would make plugin use simpler for end user and allow plugin developers to have their library still flexible for other uses. In this pattern ihp-users would just have to look to see which convenience functions are exposed for their views and controllers and keep working.

👍 Later we could add some kind of installation tool, like add-plugin (e.g. add-plugin ihp-bing) that then also automatically adds all the imports to the app based on the available module names.

In the last refactoring I actually moved away from the Helper naming as I think the Helper word is not adding any meaning. You can see this e.g. in the new modal structure here: https://github.com/digitallyinduced/ihp/tree/master/IHP/Modal

Basically this is just a renaming, but it adds a lot more clarity:

X.Helper.Controller  -> X.ControllerFunctions
X.Helper.Types       -> X.Types (e.g. the Modal submodule of IHP previously didn't even have this file. It was all in the Controller Helper)
X.Helper.View        -> X.ViewFunctions

What do you think about this structure?

We should also add a standard name for exporting stuff that is used in Config/Config.hs (like bingAPIKey). Maybe X.Config?

The ihp nix formula could allow users to specify a list of plugins they want (from what I called a curry-house ;) and then those can be checked out into the nix store. This has additional advantage that nix would make it much simpler to keep all the plugins synchronized with IHP by specifying a nixpkgs image.

Great idea, here's some code example how I imagine this could look in the default.nix:


let
    ihp = builtins.fetchGit {
        url = "https://github.com/digitallyinduced/ihp.git";
        rev = "d02a0699220a87d32889ff2a7b87ad81f8bc8195";
    };
    haskellEnv = import "${ihp}/NixSupport/default.nix" {
        ihp = ihp;
        haskellDeps = p: with p; [
            cabal-install
            base
            wai
            text
            hlint
            p.ihp
        ];
        ihpPlugins = p: with p; [ ihp-bing ];
        otherDeps = p: with p; [
            # Native dependencies, e.g. imagemagick
        ];
        projectPath = ./.;
    };
in
    haskellEnv

Maybe we could use the new nix flakes for the curry-house :)

Montmorency commented 3 years ago

In the last refactoring I actually moved away from the Helper naming as I think the Helper word is not adding any meaning.

I like the streamlined naming. I can see it being straightforward to use/extend if every plugin you want to use you can quickly see the controller/view-functions and the important types.

So maybe I could refactor layout like this?

ihp-plugin/
        PluginAPI/
        Main.hs
        Types.hs
        ControllerFunctions.hs
        ViewFunctions.hs
        Config.hs

We should also add a standard name for exporting stuff that is used in Config/Config.hs (like bingAPIKey). Maybe X.Config?

Yes that would be nice:

cat Config.hs
      data Config = Config { pluginAPIKey :: !Text
                                           , pluginAPIEndpoint :: !Text
                                           }

then I suppose option $ pluginAPIKey Bing.Config in the App/Config/Config.hs. Would make it easy and explicit for user to keep track of all their api configurations.

here's some code example how I imagine this could look in the default.nix:

Yep that looks perfect!

Not sure how to handle the import name resolutions. If there was a Plugins (CurryHouse;) dir I guess the tidiest import names would then look like:

import Plugins.Bing.ControllerFunctions
etc.

Also depends how you want to incorporate plugins in the Dev environment? Would it be interesting if there was a page with a list of plugins you can turn on/off?

mpscholten commented 3 years ago

We should also have an IHP elm plugin :) Based on the ideas of @kodeFant's blog series https://driftercode.com/blog/passing-flags-from-ihp-to-elm/

mpscholten commented 3 years ago

https://github.com/digitallyinduced/ihp/pull/725 adds the ihp-zip plugin :) Source for the plugin is at https://github.com/digitallyinduced/ihp-zip

I think it would be nice if we can put the plugins onto hackage aswell. This way the documentation would be easily googleable 👍

mpscholten commented 3 years ago

Added a new ihp-sentry plugin at https://github.com/digitallyinduced/ihp-sentry

jeyj0 commented 3 years ago

Maybe we could make use of nix-flakes (+tutorial by tweag) for plugins (or in general)? That could remove the need to add plugins inside this repo. I've also made good experience with using nix-flakes+direnv instead of lorri (#339), so this could deal with two issues at the same time?

s0kil commented 2 years ago

@jeyj0 Could you elaborate how flakes replace Lorri? It seems on NixOS you can do nixos-rebuild which allows you to replace Lorri, but not on other systems.

jeyj0 commented 2 years ago

Lorri is, at least to my knowledge, mainly useful for quickly loading a local environment, allowing you to enter and exit a nix-shell a lot faster than usual.

Since flakes are pure (https://nixos.wiki/wiki/Flakes#Making_your_evaluations_pure), there's a lot more possibilities for caching. This means entering a nix-shell created from a flake is a lot faster than entering a nix-shell otherwise.

If you want to try using flakes for your direnv integration today, the flakes docs actually have a section on "super fast nix-shell": https://nixos.wiki/wiki/Flakes#Super_fast_nix-shell.

The use_flake direnv function is now already included in direnv if I'm not mistaken, so creating that function is now not necessary anymore (I think).

If you do try this, I recommend not creating a separate shell.nix, as changes in that file will not be automatically reloaded by direnv (as mentioned here: https://nixos.wiki/wiki/Flakes#Optimize_the_reloads). Instead, simply define everything in the flake.nix file itself (alternatively, remember to touch flake.nix after any change to shell.nix).

janat08 commented 3 weeks ago

I want a PayPal plugin. Stripe doesn’t have worldwide business account coverage like PayPal. I would consider migrating payment processing parts of the app to IHP as you have to write your own integrations even in JS.