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

Plugins: Discussion of design #306

Closed
shmolf opened this issue Jan 19, 2020 · 12 comments
Closed

Plugins: Discussion of design #306

shmolf opened this issue Jan 19, 2020 · 12 comments

Comments

@shmolf
Copy link

shmolf commented Jan 19, 2020

Plugins: Some want them, all need them [see your local physician for details]

I think plugins could help expand and encapsulate functionality in the new application.

If one user wants charts, and another wants WordPress sync support, then all users should not be subjected to load time and functionality where not desired. For if one JS function fails, it could at least disrupt other functionality.

This begs the question of how to design, implement, and assign responsibility for various plugins.

The foundation of a plugin system needs to consider numerous points of conflict of views, and enable independent plugins that can share resources, whilst not disabling another (except where dependencies lay).

I myself have my own considerations, but this issue is to open a topic for other's points of view to declare their thoughts.

  • versioning
    • The app may update in a version that conflicts with a plugin.
      • should the app decline the update because of an installed plugin? Or could the app update and disable the plugin, and any dependent plugins.
  • encapsulation
    • Typically with ES6, JS Modules, TypeScript, there's more encapsulation so one plugin (app) doesn't conflict with another.
      • Should plugins ever depend on the existence of sibling plugins?
      • Should the failure of one plugin block or close the application from continuing?
        • The obvious answer may be "No", but if the plugin is as vital as an "auto-save" or "auto-sync", then something like an application block might signify an issue before the user assumes everything is okay.
      • Should there be resource restrictions?
        • A plugin may require more rendering power. This could slow down the application with machines using onboard-graphics processors. Those with independent cards may not care.
  • other considerations not disclosed here
@qrospars
Copy link

I don't have enough knowledge about this type of questions so I can't really help. But it is an important topic that should probably be discussed.
For example, I don't know if it could be considered as a plugin, but the different supports for Latex or Mermaid that we could find in the old version of Boostnote were super useful for me.

Also, I really liked the fact that loading my notes was super fast (<1s) so I would always recommend personnally to put that in front instead of plugins.

@arcturus140
Copy link
Contributor

is it necessary to introduce all these concepts from the beginning? I don't know if for example sibling plugins can be supported later on?

I am really missing my admonitions in Boost Note, that should be a small and easy plugin to start with.

@shmolf
Copy link
Author

shmolf commented Jan 30, 2020

TLDR: Plugin interaction can have side affects. Basic plugin system would be a good start.

  • should there be a market place, or install via Github URI
  • should plugins alter the settings menu, or append their own buttons to the UI (or both where applicable)
  • what are other expectations... how would you install, uninstall, or utilize a plugin?

A plugin might encompass direct Dropbox Sync support.

  • A plugin like this might depend on a specific library, which might have it's own specific dependencies.
    This is way not all extensions are compatible with your browser. Because the primary application might develop beyond the compatibility of an extension.
  • Similarly, if all plugins share resources (the same moment library), then they all need have the same version compatibility.
    • This might be resolvable by independently "compiled" plugins with their own dependency directories.

Something as important as synchronization might be important for someone who accesses their notes across devices (but isn't using the proprietary cloud storage).

  • This user may not want to update their app version if there's a conflict with this synchronization plugin.
  • Reverting is always dangerous, so if the plugin system doesn't check compatibility, then all of a sudden, there's a discrepancy between two devices.

How plugins should interact, and what limitations/responsibilities they should have, are crucial to the foundational architecture of a plugin system.

@ZeroX-DG
Copy link
Member

I agree with this idea. We need to plan out this plugin architecture as soon as possible otherwise the app will need to be restructuring and that could cost a lot of time. That's why I open an issue when this repo was first back in development: #48


  • Versioning:
    • The app version may conflict with the plugin version, however, newer version of the app may still work with the old plugin so I think we need a way to manage which functionality/API of the app are being used by the plugin and when there's a major change to the app, the app will be smart enough to notify users that the new app is not compatible with the old version of the plugin. An alternative way to deal with this is to have plugin creator to list out which version of the app that the plugin is compatible to which sounds.....exhausting but also a way to be considered.
    • Each plugin use their own dependencies versions. This is exactly what Visual Studio Code and I think a lot of other apps are doing. They will have a folder containing the plugin code and dependencies in their too.
  • Installation
    • My first thought for the plugin system is to let the user to install from the Github link & plugin creator and use Github as their way of distributing the plugins (just like vim plugin system). However, I think having a marketplace could be a better way of doing it. BoostIO already created IssueHunt as a way to encourage open-source projects & rewarding open-source creators. With the new plugin market place, BoostIO can have another way of helping open-source creators and as the same time manage & filter bad plugins (pretty much the same reason why apple or google review your app before it went on to their store).
  • Dependency
    • I think a dependency may depend on a sibling plugin, this will reduce the development time, but this may conflict with other people plugin and we need a agreement when a plugin want to depend on another. Other than that, this is a great idea since you can combine many plugins into a bigger and better plugin.
  • Blocking
    • Should the plugin block the app until it finish a certain action? Yes, that's when we need the concept of "permissions" to be introduced. Before installing a plugin, the user have to acknowledge that the plugin may cause some unexpected actions and they will have to agree it before installing.
    • Should the app block users from updating the app when it has conflicting requirement with a plugin? In my opinion, yes, the app can disable the plugin until it compatible again but also the app shouldn't update itself without user permission because the user could be using the plugin a lot and already happy with the current version of the app.

@shmolf
Copy link
Author

shmolf commented Jan 30, 2020

NPM and Composer use semantic versioning. I think it'd be good to follow through to base any plugin versioning on the this same system.

  • Plugin Dev is responsible for updating their semantic version compatibility
  • App provides a beta period for plugin devs to test their plugin with the version preview
  • GitHub URLs would be used for initial plugin installation
  • Application JSON file would maintain the Plugin list, each Plugin's URL (Github, Gitlab, Gitea, etc), and the latest installed version of the plugin.
  • Sibling Plugin dependency could be allowed, but would probably disrupt the user experience and lost confidence. Plugin devs should be focused on making fully independent plugins.
  • An app update should signify a plugin conflict, but should not block. When updated, the conflicting plugin should be disabled.
  • Uninstalled/Disabled plugins should not negatively impact the application. Any plugin should provide additional features. Removal should not affect features it did not provide.

  • Versioning

    • Often, there's a beta or pre-release. This is a perfect opportunity for plugin developers to verify the plugin works as intended, without other sideaffects.
    • If the plugin is installed via Github URI, then the plugin developer has direct control to update the compatibility file (package.json, I'm guessing).
    • If the Repo has all the committed files (node_modules and such), and if it's properly tagged, then the user can load the appropriate files for the specific plugin version they need.
      • The only question remains, is where/how will this be stored. Each users's app can't be recompiled on their specific combination of plugins.
      • So likely, that plugin repo (at the specific Tag version) will be copied to that device's plugin directory.
      • When the app starts, it could verify the Plugin list & version matches the Plugin directory's.
  • Installation

    • I think a Github link is a good start. It supports branches, tagging (for versioning), and such.
    • Later, a marketplace UI can be developed to better manage and maintain a central list.
  • Dependency

    • I suppose it would be difficult to block a plugin from depending on another. But, unless it was well maintained, it'd probably just fall out of popularity.
    • It's probably not work investing any consideration to sibling plugin dependency. A good, independent plugin will define it's own dependencies, without relying on another plugin to provide any functionality.
  • Blocking

    • A Plugin List could incorporate meta data. Similar to NPM's dependencies, where it specifies a version.
    • If the user decides to update the application regardless of the plugin, and the plugin compatibility hasn't been updated to the lates version by the developer, then the plugin should be disabled.
    • In the case where a plugin is disabled, it'd be expected that it should not negatively impact other plugins. But should announce it's own incompatibility as either a banner, setting's warning, or something.
    • Once the plugin dev has updated their compatibility, I'd think the user's app should need to be restarted before the plugin would be updated.
  • Plugin install/removal

    • We might need to take advantage of unpkg to handle repo downloads to the user's application storage location.
    • Using a basic json object to manage active/installed plugins would designate which download folders (repos) should load.
      • Similar to Vundle, the folder of a disabled plugin doesn't need to be removed until a "prune plugin" command is run, that might clear downloaded plugins that are no longer active.
    • By simply maintaining a Plugin list, "uninstalling" could be as simple as removing the item from the list.
    • Re-installing would be a check whether the plugin folder already exists, and a comparison of the cached plugin version, with the online repo's current compatible version

@ZeroX-DG
Copy link
Member

Yeah good ideas. Another way of installing the plugin is via git and clone the repo to the app directory but it will require git to be installed. However it's also a good way to consider.

If we were going to allow sibling plugin then we have to support a kind of mechanism to prevent a plugin from being removed if another plugin is depending on it.

@Rokt33r
Copy link
Member

Rokt33r commented Feb 11, 2020

What I'm thinking is like this. https://github.com/denoland/deno_website2/blob/master/src/database.json

A single repository(should be this repo) will have a file like the database.json. The file is having github url of each available plugins. To register a plugin, plugin dev will submit a PR. Once it is registered, the app will fetch the plugin's compiled asset from its releases page.

@Rokt33r
Copy link
Member

Rokt33r commented Feb 11, 2020

@ZeroX-DG @shmolf And thanks for sharing your idea. It is really helpful. I'll keep checking further discussion.

@shmolf
Copy link
Author

shmolf commented Feb 15, 2020

I like the database option. And if it pulls from the Release's page, that would be ideal. It alleviates the need for calling git clone.


One of my projects has a sort of permissions controller. Making sure an action can be taken, before it actually is.

An example of a negative scenario that might be preventable.

  • A font-plugin that can destroy Storage locations. Not even from intentional design, but more likely from a poorly designed module.

I don't think it's impossible to prevent a plugin from accessing any part of the application, and intentionally breaking the user's experience. But the idea is that the plugins will be made to enhance the users experience, so hopefully the plugin would be written with good-intentions in mind.

  • It would be preferred to have a way of restricting what modules and libraries a plugin could access.

If a basic application interface was created to give access points for plugins to work with, it would allow for plugins to safely communicate to the application, without inadvertently breaking anything.

Similarly, each plugin should be required to implement a common interface expected by the note application, so that basic communication can exist, such as version checks and the like.


Here's where I may be "tool shedding"

Even with a basic application API for which plugins can interface, it could still allow a plugin too much access. Using the Plugin list, adding another attribute for permissions would allow the application to grant specific or a collection of methods to the plugin.

Specific Boostnote Module/Lib

const init = () => { doThings(); };
const make = (cupSize) => { return brewCoffee(cupSize); };
const drink = (coffee) => { carefullySip(coffee); };
export default {
  init,
  make
};

Boostnote-defined Permission List for API.

  • Namespaces would be siblings. There's no actual tree structure. A plugin that would have access to coffee.drink wouldn't necessarily have access to coffee.
{
  "coffee": [Coffee.init],
  "coffee.make": [Coffee.init, Coffee.brew],
  "coffee.drink": [Coffee.drink]
}

And taking from @Rokt33r's database.json example

{
  "abc": {
    "type": "github",
    "owner": "zhmushan",
    "repo": "abc",
    "desc": "A better Deno framework to create web application",
    "perms": ["coffee.make"]
  }
}

The benefit of this structure, is that as long as the Plugin interfaces only through the API, they would be limited to the permissions designated.

@shmolf
Copy link
Author

shmolf commented Feb 15, 2020

Correction, the permissions shouldn't point to a specific Specific Boostnote Module/Lib. They should only point to API functions. The Specific Boostnote Module/Lib should not be directly accessible by the plugins.

@RonWalker22
Copy link

@ZeroX-DG

Sorry I'm late to the party.....

The "Central API", as mentioned in #48, is key. All the core features should be plugins based off the Central API. That's how VS Code does it:

almost every part of VS Code can be customized and enhanced through the Extension API. In fact, many core features of VS Code are built as extensions and use the same Extension API .

source: https://code.visualstudio.com/api

@Rokt33r
Copy link
Member

Rokt33r commented Mar 25, 2020

@RonWalker22 Thanks for the information. I guess I should try to make some VSCode plugin and figure out how how should we present DX.

@Rokt33r Rokt33r closed this as completed Sep 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants