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 API and documentation. #444

Closed
wants to merge 2 commits into from
Closed

Plugins API and documentation. #444

wants to merge 2 commits into from

Conversation

maxpoulin64
Copy link
Member

This is my current WIP API. I'm opening this PR to keep track of discussions and allow people to give their feedback on it. Maintainers with commit access feel free to push to this branch directly. Other people: feel free to create pull requests against the packages branch.

For now I only have created stubs for the basics, to show the general ideal. I will refine, move things around and make sure to order everything in a way that makes sense incrementally. This will likely require rewriting quite a few things for it to work, but it should be doable with a lot of copy-pasting action.

It might look a bit weird for now, but do keep in mind I have some kind of fancy RPC/data sharing between the client and the server planned, kind of like #275. I still haven't worked out the details of it. I am not planning on using EventEmitters at the moment (I will provide onXXX functions and methods to append/prepend to the function stack instead). I don't know how viable this is, but I love engineering new ways.

Design principle

My idea of a nice and powerful plugins API is to not restrict plugins at all. In order to provide plugins this, I suggest The Lounge and plugins share and run on top of the same core. Everything exposed by the core and plugins can be changed by other plugins through a practice known as monkey-patching. The idea behind this is very simple: assuming the core is sufficiently modular, most tasks that a plugin would want to achieve could be achieved by replacing or altering code in the core. Most of the currently most requested features would become relatively easy to implement in such an environment: for example, logging scrollback to a database could be accomplished by hooking the messages array and dynamically store and fetch back messages from the database backend. Another example: custom authentication and account provisionning would be achievable by replacing the current user loading function to fetch from however the backend works.

Additionally, specialized plugins will be able to provider higher level APIs which other plugins will be able to take advantage of. For example, custom command handlers could be handled by a command manager plugin that makes it easy to test/debug and change commands on a per-server/user/client basis.

Server-side and client-side plugins will run independantly, allowing users to install their own plugins without introducing a security risk on the server side. With the above point in mind, an abstraction layer could easily be made to allow running the same code on both the client and the server, dynamically using the best approach when available.

Data protection is handled by plugins by simply making variables and functions inaccessible outside of them by either not adding them to module.exports, or on the client-side by using closures.

Module installation and loading

The current plan is to load every modules on the server start, and to load every client-side modules when the page is loaded. Utility functions to support dynamic unloading of modules (by wrapping function replacements and hooking operations in a logged manner that allows restoring the original functions on unload). Unloading isn't an issue on the client (where dynamic unloading will be the most used) as the user can just reload the page.

Modules are responsible of turning themselves on and off in order to reduce the complexity of the plugins engine. If a user wishes to not use a module, said module should not be installed. The only exception to this rule will be a plugins blacklist configuration option that will allow to prevent a module from being loaded at all.

Client-side only modules, which will be installable by users, will be required to come in an archive format with all of its dependencies included as the server won't run npm or any other kind of package manager for security reasons. Server-side modules will have absolute freedom in the way they are distributed (git, npm, svn, zip archives). Their only requirement will be their availability in a specifically designated folder (either directly or through a symlink).

Client-side resources will automatically be mounted at /packages/$name/ and will point to a packages client/ directory. This is how plugins are expected to serve their client-side content.

Considerations and drawbacks

The monkey-patching method have obvious drawbacks:

  • Modules can easily take down an entire server. This particular issue can be avoided by the use of plugin wrappers running commonly used functions (custom commands, scrollback management, etc.) in try/catch blocks.
  • If API stability is not maintained, or plugins use undocumented internal APIs (which will be everything prefixed with _ in the code), then code will break.
  • It offers very limited access restriction. Client plugins will require an extra permission layer between data and the client to prevent changing internal variables.

@maxpoulin64 maxpoulin64 added Type: Feature Tickets that describe a desired feature or PRs that add them to the project. help wanted Type: Documentation Lack of documentation, improvement suggestion, or PRs that address these. Meta: Do Not Merge This PR should not be merged. labels Jul 2, 2016
@maxpoulin64 maxpoulin64 self-assigned this Jul 2, 2016
@maxpoulin64 maxpoulin64 mentioned this pull request Jul 30, 2016
@ruspow
Copy link

ruspow commented Aug 22, 2016

Just to stick my oar in..

I've 3 modules/plugins I'd like to write for the current state of thelounge as my motivations are to have a more Slack like IRC experience:

  1. - replace <3 with the heart emoji
  2. - expand youtube and other linked media, e.g. instagram so they are playable inline
  3. - expand the /j shortcut to /join

my gut feeling is that 1 and 2 are probably extensions of the front end client as they effect presentation but 3 is probably an extension for the backend as it is similar to an additional command

these might be good example ideas instead of a hello world/dolly and i'm happy to dive in and work on them if someone gives me some pointers

@maxpoulin64
Copy link
Member Author

@ruspow: it's not quite ready yet, it's more like a draft than anything else. But you can look at the eval plugin there: https://github.com/thelounge/lounge/blob/e15af1f7e1ff5217d815dbf9f934506c3126b483/packages/eval/index.js

It does not use the suggested API however, so it's still fairly limited and weird to work with.

@bpinto
Copy link

bpinto commented Aug 29, 2016

Unsure if worth mentioning, but the way https://github.com/zeit/hyperterm has developed support for plugins is interesting and quite powerful (using redux).

@astorije
Copy link
Member

astorije commented Sep 3, 2016

Unsure if worth mentioning, but the way https://github.com/zeit/hyperterm has developed support for plugins is interesting and quite powerful (using redux).

I haven't looked at their plugin API, but I noticed that they had more than 150 plugins a month after the project was created, so it seems indeed that they made it easy and powerful to write plugins!

Implements `/eval client <code>` to execute code on the client, and `/eval server <code>` to execute code on the server.
@xPaw xPaw removed the Type: Documentation Lack of documentation, improvement suggestion, or PRs that address these. label May 6, 2017
@AlMcKinlay AlMcKinlay mentioned this pull request Jun 15, 2017
@xPaw xPaw closed this Jun 25, 2017
@xPaw xPaw deleted the packages branch July 18, 2017 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Meta: Do Not Merge This PR should not be merged. Type: Feature Tickets that describe a desired feature or PRs that add them to the project.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants