You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/content/docs/dev/setup.md
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -10,7 +10,7 @@ moonlight requires [Node.js](https://nodejs.org) 22 and [pnpm](https://pnpm.io)
10
10
- Clone the repository: `git clone https://github.com/moonlight-mod/moonlight.git`
11
11
- Install dependencies: `pnpm install`.
12
12
- Build the project: `pnpm run build`.
13
-
- For working on moonlight, a watch mode is available with `pnpm run dev`.
13
+
- For working on moonlight, a watch mode is available with `pnpm run dev`. Remember that you must [restart the command in some scenarios](/ext-dev/pitfalls#restarting-dev-mode-is-required-in-some-scenarios).
14
14
15
15
For more information on project structure, [see the dedicated page](/dev/project-structure).
Copy file name to clipboardExpand all lines: src/content/docs/ext-dev/api.md
+5-1Lines changed: 5 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -21,7 +21,11 @@ The global types are available [here](https://github.com/moonlight-mod/moonlight
21
21
22
22
## Extension libraries
23
23
24
-
These libraries are built into moonlight as [core extensions](/dev/core-extensions). Remember to [add the extension dependency](/ext-dev/cookbook#using-another-extension-as-a-library) and [add the module dependency](/ext-dev/webpack#webpack-module-dependencies) before using these libraries.
24
+
These libraries are built into moonlight as [core extensions](/dev/core-extensions). See [here](/ext-dev/webpack#importing-other-webpack-modules) for an example on using them.
25
+
26
+
:::caution
27
+
Remember to add the modules you use as a dependency for your [extension](/ext-dev/manifest/#dependencies) and [module](/ext-dev/webpack#webpack-module-dependencies).
Extensions can load in three different environments:
25
-
26
-
- In the browser (the "web" environment where Discord lives): `index.ts` & Webpack modules
27
-
- On the Node.js side, where DiscordNative and such live: `node.ts`
28
-
- On the host, with little sandboxing and access to Electron APIs: `host.ts`
29
-
30
-
These map to the renderer, preload script, and main process in Electron terminology. The term "browser" is used to refer to the moonlight browser extension, while "web" refers to both the desktop and browser platforms.
10
+
Some extensions need to go beyond the scope of the Discord web application and interact with the native parts of the client. To help with this, extensions can load in one or more environments:
31
11
32
-
Most extensions only need to run code in the browser. Use the Node environment if you need access to system APIs, like the filesystem or creating processes. Use the Host environment if you need to use the Electron API.
12
+
- The "web" environment (the browser where the web app runs): `index.ts` & Webpack modules
13
+
- The "Node" environment (where DiscordNative runs, with access to Node.js APIs): `node.ts`
14
+
- The "host" environment (with little sandboxing and access to Electron APIs): `host.ts`
33
15
34
-
Remember that [you cannot directly import Node.js modules](/ext-dev/pitfalls#web-vs-nodejs), and should [share code with `moonlight.getNatives`](#sharing-code-between-nodejs-and-the-web).
16
+
These map to the renderer, preload script, and main process in Electron terminology. In moonlight internals, the term "browser" is used to refer to the moonlight browser extension, while "web" refers to theweb application that runs on the desktop app and browser site.
35
17
36
-
## Sharing code between Node.js and the web
18
+
Most extensions only run in the web environment, where the majority of the Discord client code executes in. However, extensions can run in the other environments for access to extra APIs when needed. Use system APIs as little as possible, and be mindful about [security concerns](https://www.electronjs.org/docs/latest/tutorial/context-isolation#security-considerations).
37
19
38
-
Make a `node.ts` file:
20
+
Extensions can export APIs from the Node environment and import them from the web environment using `moonlight.getNatives`:
// natives will be null if using moonlight in the browser
51
-
natives?.doSomething();
30
+
natives.doSomething();
52
31
```
53
32
54
-
Remember to [restart the dev server](/ext-dev/pitfalls#restarting-dev-mode-is-required-in-some-scenarios).
33
+
Remember to [restart the dev server](/ext-dev/pitfalls#restarting-dev-mode-is-required-in-some-scenarios) after creating `node.ts`, and that [you cannot directly import node.ts](/ext-dev/pitfalls#web-vs-nodejs).
55
34
56
-
## Using another extension as a library
57
-
58
-
Mark the extension as a dependency of your extension:
59
-
60
-
```json title="manifest.json"
61
-
{
62
-
"dependencies": ["markdown"]
63
-
}
64
-
```
65
-
66
-
Mark the Webpack module as a dependency of your own Webpack module:
On the web target (`index.ts`), you can export [patches](/ext-dev/webpack#patching), [Webpack modules](/ext-dev/webpack#webpack-module-insertion), and CSS styles:
Remember to [restart the dev server](/ext-dev/pitfalls#restarting-dev-mode-is-required-in-some-scenarios).
47
+
All exports are optional. If you aren't exporting anything from this file (e.g. your extension works entirely on the Node or host environments), you can delete `index.ts`.
90
48
91
-
## Making a custom React component
49
+
## Using React
92
50
93
-
Mark React as a dependency of your own Webpack module:
51
+
Create a [Webpack module](/ext-dev/webpack#webpack-module-insertion) with a `.tsx` file extension, then mark React as a [module dependency](/ext-dev/webpack#webpack-module-dependencies):
Then, import React from [mappings](/ext-dev/mappings):
65
+
In the module, import React from [mappings](/ext-dev/mappings):
108
66
109
67
```tsx title="webpackModules/element.tsx"
110
68
importReactfrom"@moonlight-mod/wp/react";
@@ -114,18 +72,17 @@ export default function MyElement() {
114
72
}
115
73
```
116
74
117
-
React [must be imported when using JSX](/ext-dev/pitfalls#using-jsx).
75
+
You can use this React component in a [patch](/ext-dev/webpack#patching) or through an [extension library](/ext-dev/api#app-panels). React must be imported into the scope [when using JSX](/ext-dev/pitfalls#using-jsx).
Discord internally maintains a heavily-modified fork of [Flux](https://github.com/facebookarchive/flux). Various state and events in the client are managed with Flux.
125
80
126
-
Remember to add your find to [your extension dependencies](/ext-dev/webpack#webpack-module-insertion) and [declare Spacepack as a dependency](#using-another-extension-as-a-library).
81
+
### Interacting with Flux events
127
82
128
-
## Interacting with Flux events
83
+
Flux events contain a type (e.g. `MESSAGE_CREATE`) and their associated data. They function similarly to [the Discord gateway](https://discord.com/developers/docs/events/gateway) (and some gateway events have Flux equivalents), but they are two separate concepts, and there are client-specific Flux events.
84
+
85
+
To interact with Flux events, mark `discord/Dispatcher` as a [module dependency](/ext-dev/webpack#webpack-module-dependencies), then import it from [mappings](/ext-dev/mappings) in your Webpack module:
returntrue;// return `true` to block, `false` to pass through
142
99
});
143
100
```
144
101
145
-
## Interacting with Flux stores
102
+
### Interacting with Flux stores
103
+
104
+
Flux stores contain application state and dispatch/receive events. Most Flux stores use the same central Flux dispatcher (`discord/Dispatcher`).
105
+
106
+
To interact with Flux stores, use the [Common](/ext-dev/api#common) extension library by adding it as a dependency to your [extension](/ext-dev/manifest#dependencies) and [module](/ext-dev/webpack#webpack-module-dependencies):
Flux stores can be used in React components with [the `useStateFromStores` hook](https://github.com/moonlight-mod/mappings/blob/main/src/mappings/discord/packages/flux/useStateFromStores.ts).
115
+
116
+
## Using slash commands
154
117
155
-
Remember to add `commands` to your manifest's dependencies and `{ext: "commands", id: "commands"}` to your Webpack module's dependencies.
118
+
Slash commands can be registered with the [Commands](/ext-dev/api#commands) extension library. Remember to add the Commands extension as a [extension](/ext-dev/manifest#dependencies) and [module](/ext-dev/webpack#webpack-module-dependencies) dependency.
Copy file name to clipboardExpand all lines: src/content/docs/ext-dev/getting-started.md
+6-2Lines changed: 6 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -5,6 +5,10 @@ sidebar:
5
5
order: 1
6
6
---
7
7
8
+
:::note
9
+
This page is for developers who want to make their own extensions. If you're looking for documentation on using moonlight itself, see [here](/using/getting-started).
10
+
:::
11
+
8
12
## Requirements
9
13
10
14
-[Node.js](https://nodejs.org) 22 or later
@@ -86,7 +90,7 @@ Right now, your extension doesn't do much. Let's go over what each file does:
86
90
- In `index.ts`, your extension exports its [patches](/ext-dev/webpack#patching) and [Webpack modules](/ext-dev/webpack#webpack-module-insertion). Make sure to export every patch and Webpack module you create, or else moonlight won't load them.
87
91
- If you open the Discord settings menu, you should see the "User Settings" section has been renamed to "hacked by (your extension ID) lol". This was edited by the patch in `index.ts`, which modifies Discord to insert and replace custom code.
88
92
- In the `webpackModules` folder, there are multiple Webpack modules, which is where most of your extension's code lives. Right now, all they do is log to the console.
89
-
- In `node.ts`, your extension runs [in the Node environment](/ext-dev/cookbook/#extension-entrypoints), where you can access the filesystem or spawn extra processes. Most extensions don't need to use this, though.
93
+
- In `node.ts`, your extension runs [in the Node environment](/ext-dev/cookbook#extension-entrypoints), where you can access the filesystem or spawn extra processes. Most extensions don't need to use this, though.
90
94
- In `env.d.ts` (at the root of the repository), your extension's Webpack module is declared to let you import it directly. Make sure to update this file when you add or remove Webpack modules, but don't delete it entirely.
91
95
92
96
We suggest keeping these examples around for experimentation, but you should delete what you aren't using before you publish your extension. Most extensions don't use `node.ts`, for example.
@@ -96,7 +100,7 @@ We suggest keeping these examples around for experimentation, but you should del
96
100
Run `pnpm run dev` to enter watch mode. When you make changes to your extension, the extension will automatically be rebuilt, and you can reload your client (`Ctrl+R`) to load the new version of your extension.
97
101
98
102
:::note
99
-
Watch mode will need to be restarted if you edit the extension manifest, add/remove an entrypoint, or add/remove a Webpack module. If you delete an extension, entrypoint, or Webpack module, you should run `pnpm run clean` to clean up the remaining build output.
103
+
Watch mode will need to be restarted when making certain changes or adding/removing new entrypoints. See [here](/ext-dev/pitfalls#restarting-dev-mode-is-required-in-some-scenarios) for more information.
100
104
:::
101
105
102
106
Try changing one of the logger messages, or maybe edit the example patch. Play around a bit and see what happens!
Copy file name to clipboardExpand all lines: src/content/docs/ext-dev/manifest.md
+14Lines changed: 14 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -54,6 +54,20 @@ This is an example manifest, with every value filled in:
54
54
}
55
55
```
56
56
57
+
## Dependencies
58
+
59
+
Some extensions depend on other extensions to function, like using an extension as a library. Your extension should always declare the extensions it depends on in its manifest:
60
+
61
+
```json title="manifest.json"
62
+
{
63
+
"dependencies": ["markdown"]
64
+
}
65
+
```
66
+
67
+
Additionally, when using Webpack modules from other extensions, you must [declare a dependency for your module](/ext-dev/webpack#webpack-module-dependencies) too.
68
+
69
+
moonlight will implicitly enable the extensions that your extension depends on. For extensions that aren't locally present (e.g. libraries present on an extension repository), Moonbase will prompt the user to install the required dependencies.
70
+
57
71
## Settings
58
72
59
73
There are many settings types that you can use to configure your extension in Moonbase. The types for these are available [here](https://github.com/moonlight-mod/moonlight/blob/main/packages/types/src/config.ts).
Remember to [add the module as a dependency](/ext-dev/webpack#webpack-module-dependencies) to your Webpack module.
33
+
Remember to [add the module as a dependency](/ext-dev/webpack#webpack-module-dependencies) to your Webpack module. Unlike extension libraries, mappings are built into moonlight, and do not need to be added to your extension's manifest.
34
34
35
35
## Mappings stability
36
36
37
37
The mappings repository only proxies existing Discord modules and exports. As such, if Discord removes a module or export, or a module is not properly remapped, the mapping will fail and your extension may break.
38
38
39
-
You should structure your code with the expectation that imported modules or exports may randomly fail. Use the [ErrorBoundary](/ext-dev/api#common) component provided by moonlight to safely catch errors in your UI code.
39
+
Exports and types in the mappings repository may change or be removed if Discord removes it from their own source code. In this scenario, moonlight developers are forced to remove the mapping, and we do not have the ability to bring a module back.
40
+
41
+
See [here](/ext-dev/webpack#discord-module-stability) for more information on module stability.
Copy file name to clipboardExpand all lines: src/content/docs/ext-dev/pitfalls.md
+9-7Lines changed: 9 additions & 7 deletions
Original file line number
Diff line number
Diff line change
@@ -7,22 +7,24 @@ sidebar:
7
7
8
8
## Web vs Node.js
9
9
10
-
Node.js code cannot be imported directly from the web side. You must use `moonlight.getNatives`. See [the cookbook](/ext-dev/cookbook#sharing-code-between-nodejs-and-the-web) for how to access Node.js exports.
10
+
Node.js code cannot be imported directly from the web environment. To share code between the two environments, use `moonlight.getNatives`. See [the cookbook](/ext-dev/cookbook#extension-entrypoints) for more information.
11
11
12
12
## Webpack require is not Node.js require
13
13
14
-
The `require` function used in Webpack modules and patches is not the same as the function in Node.js. Instead, it lets you require other Webpack modules by their IDs.
15
-
16
-
If you have a Webpack module you want to load, [you can require it by its ID](/ext-dev/webpack#importing-other-webpack-modules).
14
+
The `require` function used in Webpack modules and patches is not the same as the function in Node.js. Instead, it's specific to Webpack, and only works inside of Webpack modules. See [here](/ext-dev/webpack#importing-other-webpack-modules) for more information.
17
15
18
16
## The web entrypoint is not a Webpack module
19
17
20
-
You cannot use Webpack modules inside of `index.ts`, because it is loaded before Webpack is initialized. Instead, [create your own Webpack module](/ext-dev/webpack#webpack-module-insertion) and use that.
18
+
You cannot use Webpack modules inside of `index.ts`, because it is loaded before Webpack is initialized. Instead, [create your own Webpack module](/ext-dev/webpack#webpack-module-insertion) and use that instead.
21
19
22
20
## Webpack modules only load when required
23
21
24
22
By default, Webpack modules will not load unless they are required by another module or the `entrypoint` flag is set. If you need a module to run as soon as possible, [set the entrypoint flag](/ext-dev/webpack#webpack-module-insertion).
25
23
24
+
## Using ESM features
25
+
26
+
ESM-specific features (like top-level `await`) are not supported in Webpack modules or the Node or Host environments. The `index.ts` file in your extension (and *only* that file) can be compiled to ESM by [modifying your build script](https://github.com/moonlight-mod/esbuild-config/blob/8e91f1db1773380bc140c9ca3e140c30ecf5bcc3/src/factory.ts#L75).
27
+
26
28
## Spacepack findByCode matching itself
27
29
28
30
When using the `findByCode` function in Spacepack while inside of a Webpack module, you can sometimes accidentally match yourself. It is suggested to fragment the string in source but have it evaluate to the same string:
@@ -35,7 +37,7 @@ Note that esbuild will merge string concatenation, so you must be creative!
35
37
36
38
## Using JSX
37
39
38
-
[JSX](https://react.dev/learn/writing-markup-with-jsx) (and its TypeScript version, TSX) is an extension of JavaScript that allows you to write HTML-like syntax in your code. The default configuration of the build script is to convert the JSX to `React.createElement` calls:
40
+
[JSX](https://react.dev/learn/writing-markup-with-jsx) (and its TypeScript version, TSX) is an extension of JavaScript that allows you to write HTML-like syntax in your code. [Webpack modules](/ext-dev/webpack#webpack-module-insertion) with a `.tsx` filename can use JSX directly. The default configuration of the build script is to convert the JSX to `React.createElement` calls:
39
41
40
42
```tsx
41
43
const myElement = <span>Hi!</span>;
@@ -50,7 +52,7 @@ import React from "@moonlight-mod/wp/react";
50
52
const myElement = <span>Hi!</span>;
51
53
```
52
54
53
-
Remember to add React to [your extension dependencies](/ext-dev/webpack#webpack-module-insertion).
55
+
More information on using React in extensions can be found [here](/ext-dev/cookbook#using-react). Remember to add React to [your module dependencies](/ext-dev/webpack#webpack-module-insertion).
0 commit comments