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 docs for the plugin API #87

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions docs/headless-api.md
boatbomber marked this conversation as resolved.
Show resolved Hide resolved
boatbomber marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
title: Rojo Plugin APIs
sidebar_position: 7
---

The Rojo Studio plugin exposes a headless API into `game.Rojo`, which is very valuable to the Rojo ecosystem. This allows you to make companion plugins that interact with Rojo!

## Accessing the API

Plugins and command bar all share the same module cache, which allows us to expose the API through a ModuleScript located at `game.Rojo`. Using the name `"Rojo"` is easy to remember and follows branding. Once you've required Rojo, the API will be located at `Rojo.API`. For example:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Plugins and command bar all share the same module cache, which allows us to expose the API through a ModuleScript located at `game.Rojo`. Using the name `"Rojo"` is easy to remember and follows branding. Once you've required Rojo, the API will be located at `Rojo.API`. For example:
Plugins and command bar all share the same module cache, which allows us to expose the API through a ModuleScript located at `game.Rojo`. Using the name `"Rojo"` is easy to remember and is recommended. Once you've required Rojo, the API will be located at `Rojo.API`. For example:

Feels weird to mention branding in docs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This phrasing still reads a little oddly imo - maybe we should simply say "We chose the name Rojo because it is easy to remember," or alternatively, strike this sentence entirely? I don't think it's particularly necessary for the sentiment we're trying to get across here


```Lua
local Rojo = require(game.Rojo)
print(Rojo.API.Version)
```

However, plugins load in random order which means that your plugin might load before Rojo does. Therefore, the safe way to access is:

```Lua
local Rojo = require(game:WaitForChild("Rojo", math.huge))
print(Rojo.API.Version)
```

## API Documentation

### Functions

```Lua
Rojo.API:RequestAccess(plugin: Plugin, apis: {string}): boolean
```
In order to use any of the Rojo APIs, you must first explicitly request them with this function. Users will be prompted to allow/deny access to the headless API, (this function will yield until the user responds) and then the function will return a boolean which represents whether or not access was granted.

The first argument must be your `plugin` object for security and reliability purposes, and the second argument is a list of API members you're requesting access to.

**In order to keep our users safe from malicious plugins, RequestAccess must be the first function your plugin calls when using the Rojo API.** Attempting to use an API without requesting it beforehand will throw an error. The only exceptions to this are `Rojo.API.Version` and `Rojo.API.ProtocolVersion`, since those are useful in checking compatibility before any work is done.

Example Usage:
```Lua
local granted = Rojo.API:RequestAccess(plugin, {
"ProjectName",
"Address",
"Connected",
"Changed",
"CreateApiContext",
"DisconnectAsync",
"Notify",
"ConnectAsync",
"GetHostAndPort",
})
```

![requestPrompt](https://github.com/boatbomber/rojo.space/assets/40185666/ef9d0bcd-e39a-46ee-aec6-656c85699d5e)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This asset is not located in the PR! We should try to keep things local to avoid link rot.




```Lua
Rojo.API:ConnectAsync(host: string?, port: string?): void
```
Attempts to connect Rojo to the given host and port. Same behavior as the user clicking the Connect button (sync locking, etc., all behave the same).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given how messy the meaning of Async is in Roblox, it might be worth mentioning that this (and any other async API) yield and what they yield on. It's a small QoL thing for implementors to know.


```Lua
Rojo.API:DisconnectAsync(): void
```
Attempts to disconnect any active sync session.

```Lua
Rojo.API:GetSetting(setting: string): any
```
Returns the value of the given setting.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to list the settings here?


```Lua
Rojo.API:Notify(msg: string, timeout: number?, actions: { [string]: {text: string, style: string, layoutOrder: number, onClick: () -> ()} }?): () -> ()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style has to be a specific string, we should document what those are.

It might even be worth putting in the type signature, though if that ends up happening we should probably break it up into multiple lines for readability, haha.

```
Sends a Rojo notification that indicates it comes from a third-party plugin. Returns a function that dismisses the notification.

![exampleNotif](https://github.com/user-attachments/assets/ebae8c2f-ab9b-4088-8479-068d036a4243)

boatbomber marked this conversation as resolved.
Show resolved Hide resolved
```Lua
Rojo.API:GetHostAndPort(): (string, string)
```
Returns the user's chosen host and port, even if not actively connected to it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that this is what the user has inputting in the plugin right? It might be better to explain it that way, since it makes it more obvious what the difference from API.Address is.


boatbomber marked this conversation as resolved.
Show resolved Hide resolved
```Lua
Rojo.API:CreateApiContext(baseUrl: string): ApiContext
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we want to approach documenting ApiContext? It's an implementation detail right now, but if we expose this it needs to be versioned and documented.

```
Returns a new ApiContext using the given baseUrl. Useful for complex use cases that directly interface with Rojo endpoints.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Returns a new ApiContext using the given baseUrl. Useful for complex use cases that directly interface with Rojo endpoints.
Returns a new `ApiContext` using the given baseUrl. Useful for complex use cases that directly interface with Rojo endpoints.


```Lua
Rojo.API:Test(...)
```
Prints the given arguments to the console. Useful during development for testing purposes.

### Properties *(All read-only)*

```Lua
Rojo.API.Version: {number}
```
The Rojo plugin version. (Example: `{7, 2, 1}`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, we've been sitting on this PR for too long! Sorry, haha.


```Lua
Rojo.API.ProtocolVersion: number
```
The Rojo plugin's protocol version.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is, as far as I know, the only mention of protocol version in the docs. Do we want to elaborate on it a bit?


```Lua
Rojo.API.Connected: boolean
```
Whether Rojo is currently connected to a serve session.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Whether Rojo is currently connected to a serve session.
Whether Rojo is currently connected to a server.

Let's try to avoid things that invite questions like "serve session".

It's obvious to you and me what that means, but it seems like the sort of thing we'll get questions about.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be good to err on the side of specificity:

"Whether the Roblox Studio plugin is currently connected to a Rojo server"

Perhaps a little extreme, but the point stands, lol


```Lua
Rojo.API.Address: string?
```
When `Rojo.API.Connected` is `true`, this contains the address of the connected session.

```Lua
Rojo.API.ProjectName: string?
```
When `Rojo.API.Connected` is `true`, this contains the project name of the connected session.

### Events

```Lua
Rojo.API.Changed: RbxScriptSignal (changedProperty: string, newValue: any?, oldValue: any?)
```
Fires when a property of the headless API changes. Passes the name of the changed property and its new and old values.