popii-framework 0.6.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/README.md +159 -0
  2. package/dist/cli/commands.d.ts +15 -0
  3. package/dist/cli/commands.d.ts.map +1 -0
  4. package/dist/cli/pages.d.ts +5 -0
  5. package/dist/cli/pages.d.ts.map +1 -0
  6. package/dist/cli/scaffold.d.ts +23 -0
  7. package/dist/cli/scaffold.d.ts.map +1 -0
  8. package/dist/cli.d.ts +3 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +1710 -0
  11. package/dist/client.d.ts +40 -0
  12. package/dist/client.d.ts.map +1 -0
  13. package/dist/define/command.d.ts +47 -0
  14. package/dist/define/command.d.ts.map +1 -0
  15. package/dist/define/event.d.ts +52 -0
  16. package/dist/define/event.d.ts.map +1 -0
  17. package/dist/define/snap.d.ts +55 -0
  18. package/dist/define/snap.d.ts.map +1 -0
  19. package/dist/define/task.d.ts +64 -0
  20. package/dist/define/task.d.ts.map +1 -0
  21. package/dist/handler/cache.d.ts +6 -0
  22. package/dist/handler/cache.d.ts.map +1 -0
  23. package/dist/handler/context.d.ts +3 -0
  24. package/dist/handler/context.d.ts.map +1 -0
  25. package/dist/handler/index.d.ts +8 -0
  26. package/dist/handler/index.d.ts.map +1 -0
  27. package/dist/handler/interaction.d.ts +4 -0
  28. package/dist/handler/interaction.d.ts.map +1 -0
  29. package/dist/handler/lock.d.ts +2 -0
  30. package/dist/handler/lock.d.ts.map +1 -0
  31. package/dist/handler/logger.d.ts +4 -0
  32. package/dist/handler/logger.d.ts.map +1 -0
  33. package/dist/handler/message.d.ts +4 -0
  34. package/dist/handler/message.d.ts.map +1 -0
  35. package/dist/handler/middleware.d.ts +5 -0
  36. package/dist/handler/middleware.d.ts.map +1 -0
  37. package/dist/index.d.ts +31 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +10464 -0
  40. package/dist/loader/fizz.d.ts +2 -0
  41. package/dist/loader/fizz.d.ts.map +1 -0
  42. package/dist/loader/index.d.ts +3 -0
  43. package/dist/loader/index.d.ts.map +1 -0
  44. package/dist/loader/locales.d.ts +2 -0
  45. package/dist/loader/locales.d.ts.map +1 -0
  46. package/dist/loader/middleware.d.ts +54 -0
  47. package/dist/loader/middleware.d.ts.map +1 -0
  48. package/dist/loader/snaps.d.ts +3 -0
  49. package/dist/loader/snaps.d.ts.map +1 -0
  50. package/dist/loader/tasks.d.ts +3 -0
  51. package/dist/loader/tasks.d.ts.map +1 -0
  52. package/dist/plugins/activity.d.ts +15 -0
  53. package/dist/plugins/activity.d.ts.map +1 -0
  54. package/dist/plugins/ai.d.ts +35 -0
  55. package/dist/plugins/ai.d.ts.map +1 -0
  56. package/dist/plugins/automod.d.ts +12 -0
  57. package/dist/plugins/automod.d.ts.map +1 -0
  58. package/dist/plugins/canvas.d.ts +75 -0
  59. package/dist/plugins/canvas.d.ts.map +1 -0
  60. package/dist/plugins/captcha.d.ts +20 -0
  61. package/dist/plugins/captcha.d.ts.map +1 -0
  62. package/dist/plugins/commandAnalytic.d.ts +8 -0
  63. package/dist/plugins/commandAnalytic.d.ts.map +1 -0
  64. package/dist/plugins/commandLogger.d.ts +13 -0
  65. package/dist/plugins/commandLogger.d.ts.map +1 -0
  66. package/dist/plugins/desk.d.ts +23 -0
  67. package/dist/plugins/desk.d.ts.map +1 -0
  68. package/dist/plugins/economy.d.ts +41 -0
  69. package/dist/plugins/economy.d.ts.map +1 -0
  70. package/dist/plugins/errorHandler.d.ts +8 -0
  71. package/dist/plugins/errorHandler.d.ts.map +1 -0
  72. package/dist/plugins/giveaway.d.ts +21 -0
  73. package/dist/plugins/giveaway.d.ts.map +1 -0
  74. package/dist/plugins/lastfm.d.ts +24 -0
  75. package/dist/plugins/lastfm.d.ts.map +1 -0
  76. package/dist/plugins/mongoose.d.ts +23 -0
  77. package/dist/plugins/mongoose.d.ts.map +1 -0
  78. package/dist/plugins/pay.d.ts +24 -0
  79. package/dist/plugins/pay.d.ts.map +1 -0
  80. package/dist/plugins/permissionGuard.d.ts +8 -0
  81. package/dist/plugins/permissionGuard.d.ts.map +1 -0
  82. package/dist/plugins/reload.d.ts +8 -0
  83. package/dist/plugins/reload.d.ts.map +1 -0
  84. package/dist/plugins/sqlite.d.ts +20 -0
  85. package/dist/plugins/sqlite.d.ts.map +1 -0
  86. package/dist/plugins/telemetry.d.ts +11 -0
  87. package/dist/plugins/telemetry.d.ts.map +1 -0
  88. package/dist/plugins/ui.d.ts +60 -0
  89. package/dist/plugins/ui.d.ts.map +1 -0
  90. package/dist/plugins/voice/player.d.ts +9 -0
  91. package/dist/plugins/voice/player.d.ts.map +1 -0
  92. package/dist/plugins/voice/resolver.d.ts +16 -0
  93. package/dist/plugins/voice/resolver.d.ts.map +1 -0
  94. package/dist/plugins/voice/setup.d.ts +11 -0
  95. package/dist/plugins/voice/setup.d.ts.map +1 -0
  96. package/dist/plugins/voice/sponsorblock.d.ts +17 -0
  97. package/dist/plugins/voice/sponsorblock.d.ts.map +1 -0
  98. package/dist/plugins/voice/state.d.ts +35 -0
  99. package/dist/plugins/voice/state.d.ts.map +1 -0
  100. package/dist/plugins/voice/types.d.ts +14 -0
  101. package/dist/plugins/voice/types.d.ts.map +1 -0
  102. package/dist/plugins/voice/utils.d.ts +14 -0
  103. package/dist/plugins/voice/utils.d.ts.map +1 -0
  104. package/dist/plugins/voice.d.ts +72 -0
  105. package/dist/plugins/voice.d.ts.map +1 -0
  106. package/dist/plugins/web/helpers.d.ts +17 -0
  107. package/dist/plugins/web/helpers.d.ts.map +1 -0
  108. package/dist/plugins/web/index.d.ts +16 -0
  109. package/dist/plugins/web/index.d.ts.map +1 -0
  110. package/dist/plugins/web/routes/auth.d.ts +3 -0
  111. package/dist/plugins/web/routes/auth.d.ts.map +1 -0
  112. package/dist/plugins/web/routes/dashboard.d.ts +3 -0
  113. package/dist/plugins/web/routes/dashboard.d.ts.map +1 -0
  114. package/dist/plugins/web/routes/database.d.ts +3 -0
  115. package/dist/plugins/web/routes/database.d.ts.map +1 -0
  116. package/dist/plugins/web/routes/locales.d.ts +3 -0
  117. package/dist/plugins/web/routes/locales.d.ts.map +1 -0
  118. package/dist/plugins/web/routes/members.d.ts +3 -0
  119. package/dist/plugins/web/routes/members.d.ts.map +1 -0
  120. package/dist/plugins/web/routes/metrics.d.ts +7 -0
  121. package/dist/plugins/web/routes/metrics.d.ts.map +1 -0
  122. package/dist/plugins/web/routes/music.d.ts +3 -0
  123. package/dist/plugins/web/routes/music.d.ts.map +1 -0
  124. package/dist/plugins/web/routes/servers.d.ts +3 -0
  125. package/dist/plugins/web/routes/servers.d.ts.map +1 -0
  126. package/dist/plugins/web/routes/tasks.d.ts +3 -0
  127. package/dist/plugins/web/routes/tasks.d.ts.map +1 -0
  128. package/dist/plugins/web/routes/ui-editor.d.ts +3 -0
  129. package/dist/plugins/web/routes/ui-editor.d.ts.map +1 -0
  130. package/dist/plugins/web/setup.d.ts +7 -0
  131. package/dist/plugins/web/setup.d.ts.map +1 -0
  132. package/dist/plugins/web/types.d.ts +60 -0
  133. package/dist/plugins/web/types.d.ts.map +1 -0
  134. package/dist/plugins/web/views/admin.d.ts +5 -0
  135. package/dist/plugins/web/views/admin.d.ts.map +1 -0
  136. package/dist/plugins/web/views/base.d.ts +13 -0
  137. package/dist/plugins/web/views/base.d.ts.map +1 -0
  138. package/dist/plugins/web/views/commands.d.ts +2 -0
  139. package/dist/plugins/web/views/commands.d.ts.map +1 -0
  140. package/dist/plugins/web/views/dashboard.d.ts +32 -0
  141. package/dist/plugins/web/views/dashboard.d.ts.map +1 -0
  142. package/dist/plugins/web/views/database.d.ts +2 -0
  143. package/dist/plugins/web/views/database.d.ts.map +1 -0
  144. package/dist/plugins/web/views/home.d.ts +2 -0
  145. package/dist/plugins/web/views/home.d.ts.map +1 -0
  146. package/dist/plugins/web/views/index.d.ts +16 -0
  147. package/dist/plugins/web/views/index.d.ts.map +1 -0
  148. package/dist/plugins/web/views/invite.d.ts +2 -0
  149. package/dist/plugins/web/views/invite.d.ts.map +1 -0
  150. package/dist/plugins/web/views/lastfm.d.ts +2 -0
  151. package/dist/plugins/web/views/lastfm.d.ts.map +1 -0
  152. package/dist/plugins/web/views/locales.d.ts +2 -0
  153. package/dist/plugins/web/views/locales.d.ts.map +1 -0
  154. package/dist/plugins/web/views/members.d.ts +6 -0
  155. package/dist/plugins/web/views/members.d.ts.map +1 -0
  156. package/dist/plugins/web/views/music.d.ts +5 -0
  157. package/dist/plugins/web/views/music.d.ts.map +1 -0
  158. package/dist/plugins/web/views/servers.d.ts +3 -0
  159. package/dist/plugins/web/views/servers.d.ts.map +1 -0
  160. package/dist/plugins/web/views/terminal.d.ts +2 -0
  161. package/dist/plugins/web/views/terminal.d.ts.map +1 -0
  162. package/dist/plugins/web/views/ui-editor.d.ts +2 -0
  163. package/dist/plugins/web/views/ui-editor.d.ts.map +1 -0
  164. package/dist/types.d.ts +671 -0
  165. package/dist/types.d.ts.map +1 -0
  166. package/dist/utils/error.d.ts +62 -0
  167. package/dist/utils/error.d.ts.map +1 -0
  168. package/dist/utils/help.d.ts +3 -0
  169. package/dist/utils/help.d.ts.map +1 -0
  170. package/dist/utils/logger.d.ts +1 -0
  171. package/dist/utils/logger.d.ts.map +1 -0
  172. package/dist/utils/sharding.d.ts +17 -0
  173. package/dist/utils/sharding.d.ts.map +1 -0
  174. package/dist/utils/testing.d.ts +42 -0
  175. package/dist/utils/testing.d.ts.map +1 -0
  176. package/dist/utils/testing.js +192 -0
  177. package/package.json +77 -0
@@ -0,0 +1,671 @@
1
+ import type { ApplicationCommandOptionType, ApplicationCommandType, ApplicationIntegrationType, InteractionContextType, Client, LocaleString, User, GuildMember, Guild, TextBasedChannel, Attachment, Role, Message, Interaction, ClientEvents, MessageComponentInteraction, ModalSubmitInteraction, PermissionFlagsBits, Partials } from "discord.js";
2
+ import type { APIInteractionGuildMember } from "discord-api-types/v10";
3
+ export interface PopiiRedisClient {
4
+ get(key: string): Promise<string | null>;
5
+ set(key: string, value: string, mode: "PX", duration: number): Promise<unknown>;
6
+ set(key: string, value: string, mode: "PX", duration: number, flag: "NX"): Promise<string | null>;
7
+ zadd(key: string, score: number, member: string): Promise<unknown>;
8
+ zrangebyscore(key: string, min: number, max: number): Promise<string[]>;
9
+ zremrangebyscore(key: string, min: number, max: number): Promise<unknown>;
10
+ zrem(key: string, member: string): Promise<number>;
11
+ incr(key: string, expireMs: number): Promise<number>;
12
+ eval(script: string, numkeys: number, ...args: (string | number)[]): Promise<unknown>;
13
+ publish(channel: string, message: string): Promise<number>;
14
+ subscribe(channel: string): Promise<unknown>;
15
+ on(event: string, listener: (...args: any[]) => void): this;
16
+ disconnect(): void;
17
+ }
18
+ export interface PopLogger {
19
+ info(message: string, ...args: unknown[]): void;
20
+ warn(message: string, ...args: unknown[]): void;
21
+ error(message: string, ...args: unknown[]): void;
22
+ debug(message: string, ...args: unknown[]): void;
23
+ }
24
+ export interface PopOptions {
25
+ getString(name: string): string | null;
26
+ getUser(name: string): User | null;
27
+ getInteger(name: string): number | null;
28
+ getBoolean(name: string): boolean | null;
29
+ getAttachment(name: string): Attachment | null;
30
+ getChannel(name: string): TextBasedChannel | null;
31
+ getRole(name: string): Role | null;
32
+ getNumber(name: string): number | null;
33
+ getMentionable(name: string): User | Role | null;
34
+ getTargetUser(): User | null;
35
+ getTargetMessage(): Message | null;
36
+ }
37
+ export interface PopiiOption<TState = any, TInput = any, TLocals = Record<string, any>> {
38
+ name: string;
39
+ nameLocalizations?: Partial<Record<LocaleString, string>>;
40
+ description: string;
41
+ descriptionLocalizations?: Partial<Record<LocaleString, string>>;
42
+ type: ApplicationCommandOptionType;
43
+ required?: boolean;
44
+ autocomplete?: boolean | ((pop: Pop<TState, TInput, TLocals>) => Promise<void> | void);
45
+ options?: PopiiOption<TState, any, TLocals>[];
46
+ do?(pop: Pop<TState, TInput, TLocals>): Promise<void> | void;
47
+ guildOnly?: boolean;
48
+ ownerOnly?: boolean;
49
+ permissions?: (keyof typeof PermissionFlagsBits | bigint)[];
50
+ allowedRoles?: string[];
51
+ deniedRoles?: string[];
52
+ allowedChannels?: string[];
53
+ cooldown?: number | {
54
+ ms: number;
55
+ uses?: number;
56
+ scope?: "user" | "guild" | "global";
57
+ };
58
+ quota?: {
59
+ limit: number;
60
+ timeframe: number;
61
+ scope?: "user" | "guild" | "global";
62
+ };
63
+ middlewares?: PopiiMiddleware<TState, TInput, TLocals>[];
64
+ schema?: PopiiSchema;
65
+ }
66
+ export interface PopiiSchema<TInput = any> {
67
+ parse?: (data: any) => TInput;
68
+ parseAsync?: (data: any) => Promise<TInput>;
69
+ }
70
+ export interface PopiiStorageAdapter {
71
+ get(key: string): Promise<string | null>;
72
+ set(key: string, value: string, mode: "PX", duration: number): Promise<void>;
73
+ zadd(key: string, score: number, member: string): Promise<void>;
74
+ zrangebyscore(key: string, min: number, max: number): Promise<string[]>;
75
+ zremrangebyscore(key: string, min: number, max: number): Promise<void>;
76
+ zrem?(key: string, member: string): Promise<number>;
77
+ incr?(key: string, expireMs: number): Promise<number>;
78
+ setnx?(key: string, value: string, expireMs: number): Promise<boolean>;
79
+ del?(key: string): Promise<void>;
80
+ disconnect(): Promise<void>;
81
+ }
82
+ /**
83
+ * Globally augmentable interface for strongly typing `pop.locals`.
84
+ *
85
+ * Declare this in any `.d.ts` file in your project to add typed properties
86
+ * that are accessible on `pop.locals` inside every command, snap, and middleware.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * // src/types.d.ts
91
+ * declare module "popii" {
92
+ * interface PopiiLocals {
93
+ * dbUser: { id: string; balance: number; premium: boolean };
94
+ * guildConfig: Record<string, string>;
95
+ * }
96
+ * }
97
+ * ```
98
+ */
99
+ export interface PopiiLocals {
100
+ }
101
+ /**
102
+ * The base context object provided to all Popii event, command, snap, and task handlers.
103
+ *
104
+ * Every handler receives this as its first argument. It provides the client reference,
105
+ * localization helpers, a shared KV store (the Cooler), request-scoped caching,
106
+ * structured logging, and utilities for scheduling tasks and making HTTP requests.
107
+ *
108
+ * Commands and snaps receive the richer {@link Pop} subtype, which adds `reply()`,
109
+ * `defer()`, `options`, and other interaction-specific members.
110
+ *
111
+ * @category Context
112
+ *
113
+ * @example Accessing the client and logging in an event
114
+ * ```ts
115
+ * export default event(async (pop, guild) => {
116
+ * pop.log.info(`Joined ${guild.name}`);
117
+ * pop.client.discord.guilds.cache.size; // full discord.js access
118
+ * });
119
+ * ```
120
+ */
121
+ export interface EventPop<TState = any, TLocals = PopiiLocals & Record<string, any>> {
122
+ client: PopiiClient<TState>;
123
+ locale: string;
124
+ log: PopLogger;
125
+ createAttachment(path: string, name?: string): any;
126
+ fetchJSON<T = unknown>(url: string | URL | Request, init?: RequestInit): Promise<T>;
127
+ fetchText(url: string | URL | Request, init?: RequestInit): Promise<string>;
128
+ fetchBuffer(url: string | URL | Request, init?: RequestInit): Promise<ArrayBuffer>;
129
+ fetchForm<T = unknown>(url: string | URL | Request, data: FormData, init?: RequestInit): Promise<T>;
130
+ cache<T>(key: string, ttlMs: number, fetcher: () => Promise<T> | T): Promise<T>;
131
+ translate(key: string, args?: Record<string, any>): string;
132
+ t(key: string, args?: Record<string, any>): string;
133
+ cooler: {
134
+ get<T = any>(key: string): Promise<T | null>;
135
+ set(key: string, value: any, ttlMs?: number): Promise<void>;
136
+ delete(key: string): Promise<void>;
137
+ };
138
+ pack(customId: string, data: any): string;
139
+ state: TState;
140
+ locals: TLocals;
141
+ guild: Guild | null;
142
+ channel: TextBasedChannel | null;
143
+ schedule(taskName: string, payload?: any, delayMs?: number): Promise<void>;
144
+ }
145
+ /**
146
+ * The full execution context provided to command and snap handlers.
147
+ *
148
+ * Extends {@link EventPop} with interaction-specific members: `reply()`, `defer()`,
149
+ * `options` (typed slash command arguments), `input` (schema-validated input),
150
+ * and references to the raw `interaction` and `message` objects.
151
+ *
152
+ * Use the `TInput` type parameter when you supply a `schema` to the command — the
153
+ * validated result is then available as `pop.input` with full type inference.
154
+ *
155
+ * @category Context
156
+ *
157
+ * @example Reply with an embed
158
+ * ```ts
159
+ * async do(pop) {
160
+ * await pop.reply({
161
+ * embeds: [{ title: "Hello!", description: `Hey ${pop.user.username}` }],
162
+ * ephemeral: true
163
+ * });
164
+ * }
165
+ * ```
166
+ *
167
+ * @example Defer a slow command
168
+ * ```ts
169
+ * async do(pop) {
170
+ * await pop.defer();
171
+ * const result = await someSlowOperation();
172
+ * await pop.reply(result);
173
+ * }
174
+ * ```
175
+ */
176
+ export interface Pop<TState = any, TInput = any, TLocals = PopiiLocals & Record<string, any>> extends EventPop<TState, TLocals> {
177
+ reply(payload: string | {
178
+ content?: string;
179
+ embeds?: any[];
180
+ components?: any[];
181
+ files?: any[];
182
+ ephemeral?: boolean;
183
+ }): Promise<any>;
184
+ defer(options?: {
185
+ ephemeral?: boolean;
186
+ }): Promise<void>;
187
+ respond(choices: {
188
+ name: string;
189
+ value: string | number;
190
+ }[]): Promise<void>;
191
+ respondFiltered(choices: {
192
+ name: string;
193
+ value: string | number;
194
+ }[], userInput: string): Promise<void>;
195
+ user: User;
196
+ member: GuildMember | APIInteractionGuildMember | null;
197
+ options: PopOptions;
198
+ input: TInput;
199
+ interaction?: Interaction | MessageComponentInteraction | ModalSubmitInteraction;
200
+ message?: Message;
201
+ snapMatches?: RegExpMatchArray | null;
202
+ snapData?: any;
203
+ targetMessage?: Message | null;
204
+ targetUser?: User | null;
205
+ }
206
+ export interface ComponentPop<TState = any, TInput = any, TLocals = PopiiLocals & Record<string, any>> extends Pop<TState, TInput, TLocals> {
207
+ interaction: MessageComponentInteraction | ModalSubmitInteraction;
208
+ message: Message<boolean>;
209
+ }
210
+ /** Standard middleware — receives the pop context and a `next` function. Call `next(err)` to forward an error. */
211
+ export type PopiiRegularMiddleware<TState = any, TInput = any, TLocals = PopiiLocals & Record<string, any>> = (pop: Pop<TState, TInput, TLocals>, next: (err?: any) => Promise<void> | void) => Promise<void> | void;
212
+ /**
213
+ * Error-handling middleware — receives the thrown error as the first argument.
214
+ * Popii detects error middlewares by arity (function.length === 3), matching the Express convention.
215
+ * Always declare all three parameters explicitly; do not use rest args or defaults that reduce arity.
216
+ */
217
+ export type PopiiErrorMiddleware<TState = any, TInput = any, TLocals = PopiiLocals & Record<string, any>> = (err: any, pop: Pop<TState, TInput, TLocals>, next: (err?: any) => Promise<void> | void) => Promise<void> | void;
218
+ export type PopiiMiddleware<TState = any, TInput = any, TLocals = PopiiLocals & Record<string, any>> = PopiiRegularMiddleware<TState, TInput, TLocals> | PopiiErrorMiddleware<TState, TInput, TLocals>;
219
+ /** Standard component middleware — receives the component pop context and a `next` function. */
220
+ export type ComponentRegularMiddleware<TState = any, TInput = any, TLocals = PopiiLocals & Record<string, any>> = (pop: ComponentPop<TState, TInput, TLocals>, next: (err?: any) => Promise<void> | void) => Promise<void> | void;
221
+ /** Error-handling component middleware — detected by arity (function.length === 3). */
222
+ export type ComponentErrorMiddleware<TState = any, TInput = any, TLocals = PopiiLocals & Record<string, any>> = (err: any, pop: ComponentPop<TState, TInput, TLocals>, next: (err?: any) => Promise<void> | void) => Promise<void> | void;
223
+ export type ComponentMiddleware<TState = any, TInput = any, TLocals = PopiiLocals & Record<string, any>> = ComponentRegularMiddleware<TState, TInput, TLocals> | ComponentErrorMiddleware<TState, TInput, TLocals>;
224
+ /**
225
+ * The full definition of a Popii command, including its metadata, options, guards, and handler.
226
+ *
227
+ * You don't usually interact with this interface directly — use the {@link command} builder
228
+ * function, which infers all types for you.
229
+ *
230
+ * @category Core API
231
+ */
232
+ export interface PopiiCommandDefinition<TState = any, TInput = any, TLocals = PopiiLocals & Record<string, any>> {
233
+ name: string;
234
+ nameLocalizations?: Partial<Record<LocaleString, string>>;
235
+ description: string;
236
+ descriptionLocalizations?: Partial<Record<LocaleString, string>>;
237
+ type?: ApplicationCommandType;
238
+ slash?: boolean;
239
+ text?: boolean;
240
+ category?: string;
241
+ aliases?: string[];
242
+ usage?: string;
243
+ integrationTypes?: ApplicationIntegrationType[];
244
+ contexts?: InteractionContextType[];
245
+ quota?: {
246
+ limit: number;
247
+ timeframe: number;
248
+ scope?: "user" | "guild" | "global";
249
+ };
250
+ cooldown?: number | {
251
+ ms: number;
252
+ uses?: number;
253
+ scope?: "user" | "guild" | "global";
254
+ };
255
+ guildOnly?: boolean;
256
+ ownerOnly?: boolean;
257
+ premium?: boolean;
258
+ ephemeral?: boolean;
259
+ mutex?: boolean;
260
+ hidden?: boolean;
261
+ permissions?: (keyof typeof PermissionFlagsBits | bigint)[];
262
+ allowedRoles?: string[];
263
+ deniedRoles?: string[];
264
+ allowedChannels?: string[];
265
+ options?: PopiiOption<TState, any, TLocals>[];
266
+ autocomplete?(pop: Pop<TState, TInput, TLocals>): Promise<void> | void;
267
+ middlewares?: PopiiMiddleware<TState, TInput, TLocals>[];
268
+ schema?: PopiiSchema<TInput>;
269
+ /** Override the auto-defer threshold in ms. Defaults to 2000. */
270
+ deferAfter?: number;
271
+ do(pop: Pop<TState, TInput, TLocals>): Promise<void> | void;
272
+ }
273
+ /**
274
+ * The full definition of a Popii persistent component handler (Snap).
275
+ *
276
+ * You don't usually interact with this interface directly — use the {@link snap} builder
277
+ * function, which infers all types for you.
278
+ *
279
+ * @category Core API
280
+ */
281
+ export interface PopiiComponentDefinition<TState = any, TInput = any, TLocals = PopiiLocals & Record<string, any>> {
282
+ customId: string | RegExp;
283
+ prefix?: string;
284
+ guildOnly?: boolean;
285
+ ownerOnly?: boolean;
286
+ premium?: boolean;
287
+ ephemeral?: boolean;
288
+ permissions?: (keyof typeof PermissionFlagsBits | bigint)[];
289
+ allowedRoles?: string[];
290
+ deniedRoles?: string[];
291
+ allowedChannels?: string[];
292
+ mutex?: boolean;
293
+ cooldown?: number | {
294
+ ms: number;
295
+ uses?: number;
296
+ scope?: "user" | "guild" | "global";
297
+ };
298
+ quota?: {
299
+ limit: number;
300
+ timeframe: number;
301
+ scope?: "user" | "guild" | "global";
302
+ };
303
+ expiresIn?: number;
304
+ middlewares?: ComponentMiddleware<TState, TInput, TLocals>[];
305
+ schema?: PopiiSchema<TInput>;
306
+ do(pop: ComponentPop<TState, TInput, TLocals>): Promise<void> | void;
307
+ }
308
+ export interface PopiiClient<TState = any> {
309
+ config: PopiiClientConfig<TState>;
310
+ commands: Map<string, PopiiCommandDefinition<TState>>;
311
+ snaps: Map<string | RegExp, PopiiComponentDefinition<TState>>;
312
+ activeEvents: Map<string, (...args: any[]) => void>;
313
+ locales: Map<string, Record<string, string>>;
314
+ middlewares: PopiiMiddleware<TState>[];
315
+ tasks: Map<string, PopiiTaskDefinition<TState>>;
316
+ activeTasks: any[];
317
+ redis?: PopiiRedisClient;
318
+ redisSub?: PopiiRedisClient;
319
+ storage?: PopiiStorageAdapter;
320
+ _cooldowns: Map<string, {
321
+ expires: number;
322
+ usages: number;
323
+ lastUpdate: number;
324
+ }>;
325
+ _quotas: Map<string, {
326
+ expires: number;
327
+ usages: number;
328
+ }>;
329
+ _mutexes: Map<string, boolean>;
330
+ _cacheStore: Map<string, {
331
+ expires: number;
332
+ value: any;
333
+ }>;
334
+ _cacheLocks?: Map<string, Promise<any>>;
335
+ _extensions?: Map<string, (pop: EventPop) => any>;
336
+ _cleanupInterval?: any;
337
+ _logRotationInterval?: any;
338
+ _delayedJobInterval?: any;
339
+ _sseBroadcastInterval?: any;
340
+ _webRateLimitInterval?: any;
341
+ _paginationInterval?: any;
342
+ _paginationSessions?: Map<string, {
343
+ embeds: any[];
344
+ timeoutMs: number;
345
+ expires: number;
346
+ }>;
347
+ _activeCollectors?: Map<string, any>;
348
+ _commandAnalytics?: Map<string, number>;
349
+ _broadcastListeners?: Map<string, ((data: any) => void)[]>;
350
+ _sseStreams?: Map<string, any>;
351
+ isShuttingDown: boolean;
352
+ activeExecutions: number;
353
+ _pendingTimeouts?: Set<ReturnType<typeof setTimeout>>;
354
+ _executePlugins?: PopiiPlugin[];
355
+ _errorPlugins?: PopiiPlugin[];
356
+ _disabledCommands: Set<string>;
357
+ _auditLogs: any[];
358
+ _terminalLogs?: string[];
359
+ _rateLimitLogs?: any[];
360
+ _blacklist: Set<string>;
361
+ global: {
362
+ emit(event: string, data?: any): Promise<void>;
363
+ on(event: string, listener: (data: any) => void): void;
364
+ off(event: string, listener: (data: any) => void): void;
365
+ };
366
+ state: TState;
367
+ discord: Client;
368
+ start(): Promise<void>;
369
+ stop(): Promise<void>;
370
+ reload(): Promise<void>;
371
+ schedule(taskName: string, payload?: any, delayMs?: number): Promise<void>;
372
+ broadcast(event: string, data: any): Promise<void>;
373
+ offBroadcast(event: string, listener: (data: any) => void): void;
374
+ onBroadcast(event: string, listener: (data: any) => void): void;
375
+ saveState(): Promise<void>;
376
+ isPremium(userId: string, guildId?: string | null): Promise<boolean>;
377
+ reloadPlugin(name: string): Promise<boolean>;
378
+ invalidate(key: string): Promise<void>;
379
+ extend(name: string, factory: (pop: EventPop) => any): void;
380
+ setPresence(status: string): Promise<void>;
381
+ getGuildConfig?(guildId: string): Promise<Record<string, any>>;
382
+ setGuildConfig?(guildId: string, config: Record<string, any>): Promise<void>;
383
+ }
384
+ export interface PopiiServerSetting {
385
+ id: string;
386
+ label: string;
387
+ description?: string;
388
+ type: "text" | "boolean" | "select" | "channel" | "role";
389
+ options?: {
390
+ label: string;
391
+ value: string;
392
+ }[];
393
+ default?: any;
394
+ category?: string;
395
+ channelTypes?: number[];
396
+ paragraph?: boolean;
397
+ }
398
+ /**
399
+ * The definition of a scheduled background task.
400
+ *
401
+ * Use the {@link task} builder function to create one with full type inference.
402
+ * Tasks are auto-loaded from `src/tasks/` and can also be triggered on demand
403
+ * via `pop.schedule("task-name", payload, delayMs)`.
404
+ *
405
+ * @category Core API
406
+ */
407
+ export interface PopiiTaskDefinition<TState = any> {
408
+ /** A unique name for this task. Used when scheduling it via `pop.schedule()`. */
409
+ name?: string;
410
+ /** Cron expression (e.g. `"0 9 * * *"` for every day at 9am). Omit for on-demand-only tasks. */
411
+ schedule?: string;
412
+ /** IANA timezone name (e.g. `"America/New_York"`). Defaults to UTC. */
413
+ timezone?: string;
414
+ /** Allow concurrent runs of this task. Defaults to `false` (skips if previous run is still active). */
415
+ overlap?: boolean;
416
+ /** Number of times to retry on failure. Defaults to `0`. */
417
+ retries?: number;
418
+ /** Milliseconds to wait between retries. Defaults to `1000`. */
419
+ retryDelay?: number;
420
+ /** Maximum execution time in ms before the run is considered timed out. */
421
+ timeoutMs?: number;
422
+ /** The function to run. `payload` is provided when triggered via `pop.schedule()`. */
423
+ run(client: PopiiClient<TState>, payload?: any): void | Promise<void>;
424
+ }
425
+ export type PopiiEventFunction<K extends keyof ClientEvents, TState = any> = (pop: EventPop<TState>, ...args: ClientEvents[K]) => void | Promise<void>;
426
+ export interface PopiiPluginConfigField {
427
+ type: "string" | "number" | "boolean" | "select";
428
+ description?: string;
429
+ required?: boolean;
430
+ default?: unknown;
431
+ options?: string[];
432
+ /** Suggested environment variable name for this field. */
433
+ env?: string;
434
+ }
435
+ /**
436
+ * Metadata exported by community plugins for marketplace discovery.
437
+ * Place this in the `"popii"` field of your plugin's `package.json`.
438
+ *
439
+ * @category Plugins
440
+ */
441
+ export interface PopiiPluginMeta {
442
+ displayName: string;
443
+ description: string;
444
+ category?: "core" | "features" | "integrations" | "utilities" | "ui";
445
+ keywords?: string[];
446
+ /** Named export of the plugin factory function. Defaults to `"default"`. */
447
+ export?: string;
448
+ requires?: string[];
449
+ conflicts?: string[];
450
+ configSchema?: Record<string, PopiiPluginConfigField>;
451
+ }
452
+ /**
453
+ * The interface all Popii plugins must implement.
454
+ *
455
+ * A plugin is a plain object returned from a factory function. It hooks into the client
456
+ * lifecycle via `setup`, `ready`, `reload`, and `cleanup`, and can also intercept every
457
+ * command execution via `onCommandExecute` and `onCommandError`.
458
+ *
459
+ * @category Plugins
460
+ *
461
+ * @example Minimal plugin
462
+ * ```ts
463
+ * import type { PopiiPlugin } from "popii";
464
+ *
465
+ * export function myPlugin(): PopiiPlugin {
466
+ * return {
467
+ * name: "my-plugin",
468
+ * setup(client) {
469
+ * // runs once at startup — register listeners, create DB tables, etc.
470
+ * },
471
+ * ready(client) {
472
+ * // runs after Discord connects — safe to use client.discord.guilds.cache
473
+ * },
474
+ * cleanup(client) {
475
+ * // runs on graceful shutdown — clear intervals, close connections
476
+ * }
477
+ * };
478
+ * }
479
+ * ```
480
+ */
481
+ export interface PopiiPlugin<TState = any> {
482
+ name: string;
483
+ /**
484
+ * Plugin names that must be loaded before this plugin.
485
+ * Popii throws at startup if any listed plugin is missing.
486
+ */
487
+ requires?: string[];
488
+ /**
489
+ * Plugin names this plugin cannot coexist with.
490
+ * Popii throws at startup if any listed plugin is also present.
491
+ */
492
+ conflicts?: string[];
493
+ /**
494
+ * Execution order during the setup lifecycle. Higher values run first.
495
+ * @default 0
496
+ */
497
+ priority?: number;
498
+ /**
499
+ * Declarative per-guild settings exposed in the web dashboard's server settings form.
500
+ * The category defaults to the plugin name if omitted.
501
+ */
502
+ settingsSchema?: PopiiServerSetting[];
503
+ /** Runs once at startup, before connecting to Discord. Register listeners and create DB tables here. */
504
+ setup(client: PopiiClient<TState>): void | Promise<void>;
505
+ /** Runs after the bot successfully connects to Discord. Safe to access guild and user caches. */
506
+ ready?(client: PopiiClient<TState>): void | Promise<void>;
507
+ /** Runs after a hot-reload. Re-wrap commands with middleware or refresh state here. */
508
+ reload?(client: PopiiClient<TState>): void | Promise<void>;
509
+ /** Runs on graceful shutdown. Clear intervals and close external connections here. */
510
+ cleanup?(client: PopiiClient<TState>): void | Promise<void>;
511
+ /** Called before every command or snap executes. Useful for analytics and tracing. */
512
+ onCommandExecute?(pop: Pop<TState>, command: PopiiCommandDefinition<TState> | PopiiComponentDefinition<TState>): void | Promise<void>;
513
+ /** Called when a command or snap throws an unhandled error. */
514
+ onCommandError?(error: unknown, pop: Pop<TState>): void | Promise<void>;
515
+ /** Called when a new `pop` context is created. Inject data into the context here. */
516
+ onContextCreate?(pop: EventPop<TState>): void;
517
+ }
518
+ /**
519
+ * Configuration passed to {@link popiiClient} when creating the bot.
520
+ *
521
+ * Only `token` is required. Everything else has sensible defaults.
522
+ *
523
+ * @category Core API
524
+ *
525
+ * @example Minimal setup
526
+ * ```ts
527
+ * const client = popiiClient({ token: process.env.DISCORD_TOKEN! });
528
+ * ```
529
+ *
530
+ * @example Full setup with common options
531
+ * ```ts
532
+ * const client = popiiClient({
533
+ * token: process.env.DISCORD_TOKEN!,
534
+ * devGuildId: process.env.DEV_GUILD_ID,
535
+ * owners: ["your_discord_user_id"],
536
+ * prefix: "!",
537
+ * status: ["Serving {{guilds}} servers", "Try /help"],
538
+ * plugins: [sqlitePlugin(), webPlugin(), errorHandlerPlugin()],
539
+ * });
540
+ * ```
541
+ */
542
+ export interface PopiiClientConfig<TState = any> {
543
+ /** Your Discord bot token. Keep this in `.env` — never commit it. */
544
+ token: string;
545
+ /**
546
+ * Connection mode.
547
+ * - `"websocket"` (default) — standard Gateway connection.
548
+ * - `"http"` — HTTP interactions endpoint for serverless deployments. Requires `publicKey` and `port`.
549
+ */
550
+ mode?: "websocket" | "http";
551
+ /** Required when `mode` is `"http"`. Your application's public key from the Discord Developer Portal. */
552
+ publicKey?: string;
553
+ /** Port for the HTTP interactions server when `mode` is `"http"`. Defaults to `3000`. */
554
+ port?: number;
555
+ /**
556
+ * Enables legacy text commands. Provide a string prefix (e.g. `"!"`) or a function
557
+ * that returns the prefix(es) per message.
558
+ */
559
+ prefix?: string | ((message: Message) => string | string[] | Promise<string | string[] | null> | null);
560
+ /** Override the auto-detected Gateway intents. Popii infers intents from your event filenames by default. */
561
+ intents?: number[];
562
+ /** Redis connection URL (e.g. `"redis://localhost:6379"`). Enables Redis-backed storage and sharding coordination. */
563
+ redisUrl?: string;
564
+ /** Alternative to `redisUrl`. Pass a connection string or an ioredis options object. */
565
+ redis?: string | Record<string, unknown>;
566
+ /** Provide a custom storage adapter to replace the built-in in-process Map with any backend. */
567
+ storage?: PopiiStorageAdapter;
568
+ /** Override the auto-detected Discord.js Partials. Popii infers partials from your event filenames by default. */
569
+ partials?: Partials[];
570
+ /**
571
+ * A guild ID used to register slash commands during development.
572
+ * Guild commands sync instantly; global commands can take up to an hour.
573
+ * Remove or leave empty in production.
574
+ */
575
+ devGuildId?: string;
576
+ /** Called when a command or snap throws an error that is not caught by a middleware. */
577
+ onError?: (error: unknown, pop: Pop) => void | Promise<void>;
578
+ /** Called for unhandled promise rejections and uncaught exceptions not tied to a command. */
579
+ onGlobalError?: (error: unknown) => void | Promise<void>;
580
+ /** Discord user IDs that have bot-owner privileges (e.g. `ownerOnly: true` commands). */
581
+ owners?: string[];
582
+ /** Initial value for `pop.state` and `client.state`. Persisted to Redis/storage between restarts. */
583
+ state?: TState;
584
+ commands?: {
585
+ dir?: string;
586
+ /**
587
+ * Automatically maps nested folders into subcommands and subcommand groups.
588
+ * e.g. `src/commands/config/set.ts` becomes `/config set`.
589
+ *
590
+ * @default true
591
+ */
592
+ folderRouting?: boolean;
593
+ /**
594
+ * Automatically sync Slash Commands to Discord on startup.
595
+ * Disable this in production to prevent rate-limits, and use `popii sync` instead.
596
+ * @default true
597
+ */
598
+ autoSync?: boolean;
599
+ };
600
+ /**
601
+ * Configure or disable the built-in `/help` command.
602
+ * Set to `false` to disable it entirely, or an object to customise the command name and aliases.
603
+ */
604
+ help?: boolean | {
605
+ enabled?: boolean;
606
+ command?: string;
607
+ aliases?: string[];
608
+ };
609
+ /**
610
+ * Bot status/activity string. Pass an array to rotate between multiple statuses.
611
+ * Supports template tokens: `{{guilds}}`, `{{users}}`, `{{shardId}}`.
612
+ */
613
+ status?: string | string[];
614
+ /** Interval in ms between status rotations when `status` is an array. Defaults to 30000. */
615
+ statusInterval?: number;
616
+ /** Plugins to load. Plugins run in list order (highest `priority` first within that order). */
617
+ plugins?: PopiiPlugin<TState>[];
618
+ /**
619
+ * When `true`, Popii scans `node_modules` for installed `popii-plugin-*` packages
620
+ * (identified by a `"popii"` field in their `package.json`) and loads them automatically.
621
+ * Explicitly registered plugins in `plugins` always take precedence.
622
+ * @default false
623
+ */
624
+ autoDiscover?: boolean;
625
+ pluginConfig?: Record<string, unknown>;
626
+ /** Override the directory Popii scans for event files. Defaults to `"./src/events"`. */
627
+ events?: {
628
+ dir?: string;
629
+ };
630
+ /** Override the directory Popii scans for snap files. Defaults to `"./src/snaps"`. */
631
+ snaps?: {
632
+ dir?: string;
633
+ };
634
+ /** Override the directory Popii scans for middleware files. Defaults to `"./src/middlewares"`. */
635
+ middlewares?: {
636
+ dir?: string;
637
+ };
638
+ /** Override the directory Popii scans for task files. Defaults to `"./src/tasks"`. */
639
+ tasks?: {
640
+ dir?: string;
641
+ };
642
+ /**
643
+ * Localization configuration.
644
+ * - `dir` — directory containing `<locale>.json` files. Defaults to `"./src/locales"`.
645
+ * - `default` — fallback locale code. Defaults to `"en-US"`.
646
+ * - `url` — remote URL to fetch locale files from (fetched at startup).
647
+ */
648
+ locales?: {
649
+ dir?: string;
650
+ default?: string;
651
+ url?: string;
652
+ };
653
+ /** Custom logger implementation. Defaults to the built-in Popii logger. */
654
+ logger?: PopLogger;
655
+ /** Write logs to rotating files in `./logs/`. Defaults to `false`. */
656
+ fileLogging?: boolean;
657
+ /** Emit log lines as newline-delimited JSON instead of human-readable text. */
658
+ structuredLogs?: boolean;
659
+ /**
660
+ * Controls how rotating status messages are coordinated across shards.
661
+ * - `'local'` (default): each shard rotates independently.
662
+ * - `'coordinated'`: shard 0 leads rotation and broadcasts the active status
663
+ * to all other shards via Redis pub/sub or IPC so they all show the same string.
664
+ * Supports template tokens: `{{shardId}}`, `{{guilds}}`, `{{users}}`.
665
+ */
666
+ presenceStrategy?: "local" | "coordinated";
667
+ /** TTL in milliseconds for persisted bot state in Redis/storage. Defaults to 90 days. */
668
+ stateTtlMs?: number;
669
+ serverSettings?: PopiiServerSetting[];
670
+ }
671
+ //# sourceMappingURL=types.d.ts.map