239 lines
5.5 kB
1
import { ExtensionSettingsManifest } from "./config";
2
import { Snowflake } from "./discord";
3
import { WebpackModuleFunc } from "./discord/webpack";
4
5
export enum ExtensionTag {
6
Accessibility = "accessibility",
7
Appearance = "appearance",
8
Chat = "chat",
9
Commands = "commands",
10
ContextMenu = "contextMenu",
11
DangerZone = "dangerZone",
12
Development = "development",
13
Fixes = "fixes",
14
Fun = "fun",
15
Markdown = "markdown",
16
Voice = "voice",
17
Privacy = "privacy",
18
Profiles = "profiles",
19
QualityOfLife = "qol",
20
Library = "library"
21
}
22
23
export type ExtensionAuthor =
24
| string
25
| {
26
name: string;
27
id?: Snowflake;
28
};
29
30
export type ExtensionManifest = {
31
$schema?: string;
32
33
/**
34
* A unique identifier for your extension.
35
*/
36
id: string;
37
38
/**
39
* A version string for your extension - doesn't need to follow a specific format. Required for publishing.
40
*/
41
version?: string;
42
43
/**
44
* The API level this extension targets. If it does not match the current version, the extension will not be loaded.
45
*/
46
apiLevel?: number;
47
48
/**
49
* Which environment this extension is capable of running in.
50
*/
51
environment?: ExtensionEnvironment;
52
53
/**
54
* Metadata about your extension for use in Moonbase.
55
*/
56
meta?: {
57
/**
58
* A human friendly name for your extension as a proper noun.
59
*/
60
name?: string;
61
62
/**
63
* A short tagline that appears below the name.
64
*/
65
tagline?: string;
66
67
/**
68
* A longer description that can use Markdown.
69
*/
70
description?: string;
71
72
/**
73
* List of authors that worked on this extension - accepts string or object with ID.
74
*/
75
authors?: ExtensionAuthor[];
76
77
/**
78
* A list of tags that are relevant to the extension.
79
*/
80
tags?: ExtensionTag[];
81
82
/**
83
* The URL to the source repository.
84
*/
85
source?: string;
86
87
/**
88
* A donation link (or other method of support). If you don't want financial contributions, consider putting your favorite charity here!
89
*/
90
donate?: string;
91
92
/**
93
* A changelog to show in Moonbase.
94
* Moonbase will show the changelog for the latest version, even if it is not installed.
95
*/
96
changelog?: string;
97
98
/**
99
* Whether the extension is deprecated and no longer receiving updates.
100
*/
101
deprecated?: boolean;
102
};
103
104
/**
105
* A list of extension IDs that are required for the extension to load.
106
*/
107
dependencies?: string[];
108
109
/**
110
* A list of extension IDs that the user may want to install.
111
*/
112
suggested?: string[];
113
114
/**
115
* A list of extension IDs that the extension is incompatible with.
116
* If two incompatible extensions are enabled, one of them will not load.
117
*/
118
incompatible?: string[];
119
120
/**
121
* A list of settings for your extension, where the key is the settings ID.
122
*/
123
settings?: Record<string, ExtensionSettingsManifest>;
124
125
/**
126
* A list of URLs to bypass CORS for.
127
* This is implemented by checking if the start of the URL matches.
128
* @example https://moonlight-mod.github.io/
129
*/
130
cors?: string[];
131
132
/**
133
* A list of URLs to block all requests to.
134
* This is implemented by checking if the start of the URL matches.
135
* @example https://moonlight-mod.github.io/
136
*/
137
blocked?: string[];
138
139
/**
140
* A mapping from CSP directives to URLs to allow.
141
* @example { "script-src": ["https://example.com"] }
142
*/
143
csp?: Record<string, string[]>;
144
};
145
146
export enum ExtensionEnvironment {
147
/**
148
* The extension will run on both platforms, the host/native modules MAY be loaded
149
*/
150
Both = "both",
151
152
/**
153
* Extension will run on desktop only, the host/native modules are guaranteed to load
154
*/
155
Desktop = "desktop",
156
157
/**
158
* Currently equivalent to Both
159
*/
160
Web = "web"
161
}
162
163
export enum ExtensionLoadSource {
164
Developer,
165
Core,
166
Normal
167
}
168
169
export type DetectedExtension = {
170
id: string;
171
manifest: ExtensionManifest;
172
source: { type: ExtensionLoadSource; url?: string };
173
scripts: {
174
web?: string;
175
webPath?: string;
176
webpackModules?: Record<string, string>;
177
nodePath?: string;
178
hostPath?: string;
179
style?: string;
180
};
181
};
182
183
export type ProcessedExtensions = {
184
extensions: DetectedExtension[];
185
dependencyGraph: Map<string, Set<string> | null>;
186
};
187
188
export type PatchMatch = string | RegExp;
189
export type PatchReplaceFn = (substring: string, ...args: string[]) => string;
190
export type PatchReplaceModule = (orig: string) => WebpackModuleFunc;
191
192
export enum PatchReplaceType {
193
Normal,
194
Module
195
}
196
197
export type PatchReplace =
198
| {
199
type?: PatchReplaceType.Normal;
200
match: PatchMatch;
201
replacement: string | PatchReplaceFn;
202
}
203
| {
204
type: PatchReplaceType.Module;
205
replacement: PatchReplaceModule;
206
};
207
208
export type Patch = {
209
find: PatchMatch;
210
replace: PatchReplace | PatchReplace[];
211
hardFail?: boolean; // if any patches fail, all fail
212
prerequisite?: () => boolean;
213
};
214
215
export type ExplicitExtensionDependency = {
216
ext?: string;
217
id: string;
218
};
219
220
export type ExtensionDependency = string | RegExp | ExplicitExtensionDependency;
221
222
export type ExtensionWebpackModule = {
223
entrypoint?: boolean;
224
dependencies?: ExtensionDependency[];
225
run?: WebpackModuleFunc;
226
};
227
228
export type ExtensionWebExports = {
229
patches?: Patch[];
230
webpackModules?: Record<string, ExtensionWebpackModule>;
231
styles?: string[];
232
};
233
234
export type IdentifiedPatch = Patch & {
235
ext: string;
236
id: number;
237
};
238
239
export type IdentifiedWebpackModule = ExtensionWebpackModule & ExplicitExtensionDependency;
240