@stoatx/client 0.6.4 → 0.7.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.
- package/README.md +3 -113
- package/dist/index.cjs +189 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +105 -5
- package/dist/index.d.ts +105 -5
- package/dist/index.js +189 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,127 +5,17 @@ A high-performance, fully-typed, and memory-efficient client library for the Sto
|
|
|
5
5
|
[](https://www.npmjs.com/package/@stoatx/client)
|
|
6
6
|
[](https://www.typescriptlang.org/)
|
|
7
7
|
|
|
8
|
-
`@stoatx/client` provides a robust object-oriented wrapper around Stoat's REST and WebSocket APIs. It features an intelligent caching system, automatic memory sweeping, and strict event typings to make building bots as frictionless as possible.
|
|
9
|
-
|
|
10
8
|
## Features
|
|
11
9
|
|
|
12
10
|
- **Strictly Typed:** 100% TypeScript with highly accurate generic types for events and structures.
|
|
13
11
|
- **Smart Caching:** Built on a unified `BaseManager` architecture that guarantees reference stability (no duplicate objects in memory).
|
|
14
12
|
- **Automatic Memory Management:** Includes a built-in `SweeperManager` to prevent memory leaks in long-running applications.
|
|
15
13
|
- **Extensible:** Designed to seamlessly integrate with higher-level command frameworks like the Stoatx Handler.
|
|
14
|
+
- **Self-hosting support:** Natively supports custom Stoat instances via root API discovery.
|
|
16
15
|
- **Modern Node:** Pure ESM and CommonJS support built with `tsup`.
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
# Using pnpm (Recommended)
|
|
22
|
-
pnpm add @stoatx/client
|
|
23
|
-
|
|
24
|
-
# Using npm
|
|
25
|
-
npm install @stoatx/client
|
|
26
|
-
|
|
27
|
-
# Using yarn
|
|
28
|
-
yarn add @stoatx/client
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Quick Start
|
|
32
|
-
|
|
33
|
-
```typescript
|
|
34
|
-
import { Client } from "@stoatx/client";
|
|
35
|
-
|
|
36
|
-
// Initialize the client
|
|
37
|
-
const client = new Client({
|
|
38
|
-
sweepers: {
|
|
39
|
-
messages: {
|
|
40
|
-
lifetime: 3600000, // 1 hour
|
|
41
|
-
interval: 600000, // 10 minutes
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
// Listen to events
|
|
47
|
-
client.on("ready", async () => {
|
|
48
|
-
const me = await client.users.fetchMe();
|
|
49
|
-
console.log(`Logged in successfully as ${me.username}!`);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
client.on("messageCreate", async (message) => {
|
|
53
|
-
if (message.author.bot) return;
|
|
54
|
-
|
|
55
|
-
if (message.content === "!ping") {
|
|
56
|
-
await message.channel.send("Pong! 🏓");
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// Connect to Stoat
|
|
61
|
-
client.login("YOUR_BOT_TOKEN");
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
##️ Architecture & Managers
|
|
65
|
-
|
|
66
|
-
`@stoatx/client` organizes data using a predictable **Manager** hierarchy. Managers handle fetching, caching, and editing structures.
|
|
67
|
-
|
|
68
|
-
### Global Managers
|
|
69
|
-
|
|
70
|
-
Accessible directly on the `client`, managing data across the entire bot:
|
|
71
|
-
|
|
72
|
-
- `client.users` (Fetches and caches users)
|
|
73
|
-
- `client.servers` (Fetches and caches servers)
|
|
74
|
-
- `client.channels` (The global cache for all channel types)
|
|
75
|
-
|
|
76
|
-
### Scoped Managers
|
|
77
|
-
|
|
78
|
-
Accessible on specific structures (like `Server` or `Channel`), managing localized data:
|
|
79
|
-
|
|
80
|
-
- `server.members` (Manages members within a specific server)
|
|
81
|
-
- `server.roles` (Manages roles for a server)
|
|
82
|
-
- `server.channels` (A virtual manager filtering the global channel cache)
|
|
83
|
-
- `channel.messages` (Manages messages within a specific channel)
|
|
84
|
-
|
|
85
|
-
### Example: Editing a Server and Sending a Message
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
// Fetch a server and edit its name
|
|
89
|
-
const server = await client.servers.fetch("SERVER_ID");
|
|
90
|
-
await server.edit({ name: "My Awesome Server" });
|
|
91
|
-
|
|
92
|
-
// Find a specific channel and send an embed
|
|
93
|
-
const channel = server.channels.cache.get("CHANNEL_ID");
|
|
94
|
-
if (channel && channel.isText()) {
|
|
95
|
-
await channel.send({
|
|
96
|
-
content: "Welcome to the new server!",
|
|
97
|
-
embeds: [{ title: "Update", description: "Name changed successfully." }],
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Building Command Handlers
|
|
103
|
-
|
|
104
|
-
While you can use `@stoatx/client` directly, it truly shines when paired with a command handler. Because the events are strictly typed using generics, you can easily build type-safe event registries.
|
|
105
|
-
We recommend using the `Stoatx` for a seamless experience, but you can also create your own custom command handler leveraging the client's event system.
|
|
106
|
-
|
|
107
|
-
```typescript
|
|
108
|
-
// Example of event listening
|
|
109
|
-
import type { ClientEvents } from "@stoatx/client";
|
|
110
|
-
|
|
111
|
-
function registerEvent<K ClientEvents extends keyof>(
|
|
112
|
-
client: Client,
|
|
113
|
-
event: K,
|
|
114
|
-
handler: (...args: ClientEvents[K]) => void
|
|
115
|
-
) {
|
|
116
|
-
client.on(event, handler);
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## Contributing
|
|
121
|
-
|
|
122
|
-
Contributions are welcome! If you're using this library and find a bug or want to add a feature from the Revolt API, feel free to open a Pull Request.
|
|
123
|
-
|
|
124
|
-
1. Clone the repository.
|
|
125
|
-
2. Run `pnpm install`.
|
|
126
|
-
3. Make your changes in `packages/client`.
|
|
127
|
-
4. Run `pnpm build` to ensure `tsup` compiles your changes correctly.
|
|
17
|
+
For installation instructions, guides, and API references, visit the **[Stoatx Documentation](https://stoatx-ts.github.io/stoatx/)**.
|
|
128
18
|
|
|
129
19
|
## License
|
|
130
20
|
|
|
131
|
-
MIT © [Stoatx / Stoatx Team]
|
|
21
|
+
MIT © [Stoatx / Stoatx Team]
|
package/dist/index.cjs
CHANGED
|
@@ -829,6 +829,7 @@ var GatewayManager = class {
|
|
|
829
829
|
this.client = client;
|
|
830
830
|
}
|
|
831
831
|
ws = null;
|
|
832
|
+
wsURL = "";
|
|
832
833
|
pingInterval = null;
|
|
833
834
|
token = null;
|
|
834
835
|
reconnectAttempts = 0;
|
|
@@ -843,7 +844,7 @@ var GatewayManager = class {
|
|
|
843
844
|
this.ws.removeAllListeners();
|
|
844
845
|
this.ws = null;
|
|
845
846
|
}
|
|
846
|
-
const baseUrl = "wss://stoat.chat
|
|
847
|
+
const baseUrl = this.wsURL ?? "wss://events.stoat.chat";
|
|
847
848
|
const url = `${baseUrl}?version=1&format=json&token=${this.token}`;
|
|
848
849
|
this.ws = new import_ws.default(url);
|
|
849
850
|
this.ws.on("open", () => {
|
|
@@ -863,6 +864,9 @@ var GatewayManager = class {
|
|
|
863
864
|
this.client.emit("error", error);
|
|
864
865
|
});
|
|
865
866
|
}
|
|
867
|
+
setGatewayUrl(url) {
|
|
868
|
+
this.wsURL = url;
|
|
869
|
+
}
|
|
866
870
|
handleMessage(rawData) {
|
|
867
871
|
const payload = JSON.parse(rawData.toString());
|
|
868
872
|
const eventType = payload.type;
|
|
@@ -1359,12 +1363,19 @@ var RESTManager = class {
|
|
|
1359
1363
|
}
|
|
1360
1364
|
}, 3e5).unref();
|
|
1361
1365
|
}
|
|
1362
|
-
baseURL = "
|
|
1366
|
+
baseURL = "";
|
|
1367
|
+
cdnURL = "";
|
|
1363
1368
|
token = null;
|
|
1364
1369
|
buckets = /* @__PURE__ */ new Map();
|
|
1365
1370
|
setToken(token) {
|
|
1366
1371
|
this.token = token;
|
|
1367
1372
|
}
|
|
1373
|
+
setBaseURL(baseURL) {
|
|
1374
|
+
this.baseURL = baseURL.replace(/\/+$/, "");
|
|
1375
|
+
}
|
|
1376
|
+
setCDNURL(cdnURL) {
|
|
1377
|
+
this.cdnURL = cdnURL.replace(/\/+$/, "");
|
|
1378
|
+
}
|
|
1368
1379
|
/**
|
|
1369
1380
|
* Generates a local identifier for the bucket based on method and path.
|
|
1370
1381
|
*/
|
|
@@ -1456,7 +1467,7 @@ var RESTManager = class {
|
|
|
1456
1467
|
*/
|
|
1457
1468
|
async uploadFile(tag, fileBuffer, filename) {
|
|
1458
1469
|
if (!this.token) throw new Error("REST_NOT_READY: No token available.");
|
|
1459
|
-
const url =
|
|
1470
|
+
const url = `${this.cdnURL}/${tag}`;
|
|
1460
1471
|
const formData = new FormData();
|
|
1461
1472
|
formData.append("file", new Blob([fileBuffer]), filename);
|
|
1462
1473
|
const response = await fetch(url, {
|
|
@@ -3852,6 +3863,50 @@ var Emoji = class extends Base {
|
|
|
3852
3863
|
if (data.animated !== void 0) this.animated = data.animated;
|
|
3853
3864
|
if (data.nsfw !== void 0) this.nsfw = data.nsfw;
|
|
3854
3865
|
}
|
|
3866
|
+
/**
|
|
3867
|
+
* Fetch this emoji from the API or resolves it from the local cache.
|
|
3868
|
+
* @param force Whether to skip the cache check and force a direct API request. Defaults to false.
|
|
3869
|
+
* @returns A promise that resolves to the fetched {@link Emoji} object.
|
|
3870
|
+
* @throws {Error} If the API request fails or if the emoji is detached.
|
|
3871
|
+
* @example
|
|
3872
|
+
* // Force fetch emoji to update its data
|
|
3873
|
+
* await emoji.fetch(true);
|
|
3874
|
+
*/
|
|
3875
|
+
async fetch(force) {
|
|
3876
|
+
const server = this.client.servers.cache.get(this.parent.type === "Server" ? this.parent.id : "");
|
|
3877
|
+
if (!server) throw new Error("No server registered in EmojiManager");
|
|
3878
|
+
if (this.parent.type === "Detached") throw new Error("Cannot fetch a detached emoji");
|
|
3879
|
+
return await server.emojis.fetch(this, force);
|
|
3880
|
+
}
|
|
3881
|
+
/**
|
|
3882
|
+
* Deletes this emoji from the server.
|
|
3883
|
+
* @returns A promise that resolves when the emoji has been deleted.
|
|
3884
|
+
* @throws {Error} If the API request fails or if the emoji is detached.
|
|
3885
|
+
* @example
|
|
3886
|
+
* // Delete an emoji from the server
|
|
3887
|
+
* await emoji.delete();
|
|
3888
|
+
*/
|
|
3889
|
+
async delete() {
|
|
3890
|
+
const server = this.client.servers.cache.get(this.parent.type === "Server" ? this.parent.id : "");
|
|
3891
|
+
if (!server) throw new Error("No server registered in EmojiManager");
|
|
3892
|
+
if (this.parent.type === "Detached") throw new Error("Emoji is already detached");
|
|
3893
|
+
await server.emojis.delete(this);
|
|
3894
|
+
}
|
|
3895
|
+
/**
|
|
3896
|
+
* Edits this emoji's properties.
|
|
3897
|
+
* @param options The options to edit the emoji with.
|
|
3898
|
+
* @returns A promise that resolves to the edited {@link Emoji} object.
|
|
3899
|
+
* @throws {Error} If the API request fails or if the emoji is detached.
|
|
3900
|
+
* @example
|
|
3901
|
+
* // Edit an emoji's name
|
|
3902
|
+
* await emoji.edit({ name: "new_name" });
|
|
3903
|
+
*/
|
|
3904
|
+
async edit(options) {
|
|
3905
|
+
const server = this.client.servers.cache.get(this.parent.type === "Server" ? this.parent.id : "");
|
|
3906
|
+
if (!server) throw new Error("No server registered in EmojiManager");
|
|
3907
|
+
if (this.parent.type === "Detached") throw new Error("Cannot edit a detached emoji");
|
|
3908
|
+
return await server.emojis.edit(this, options);
|
|
3909
|
+
}
|
|
3855
3910
|
};
|
|
3856
3911
|
|
|
3857
3912
|
// src/managers/EmojiManager.ts
|
|
@@ -3865,7 +3920,7 @@ var EmojiManager = class extends BaseManager {
|
|
|
3865
3920
|
* Tell BaseManager how to find the ID for Emojis
|
|
3866
3921
|
*/
|
|
3867
3922
|
extractId(data) {
|
|
3868
|
-
return data._id
|
|
3923
|
+
return data._id;
|
|
3869
3924
|
}
|
|
3870
3925
|
/**
|
|
3871
3926
|
* Tell BaseManager how to build an Emoji
|
|
@@ -3873,10 +3928,104 @@ var EmojiManager = class extends BaseManager {
|
|
|
3873
3928
|
construct(data) {
|
|
3874
3929
|
return new Emoji(this.client, data);
|
|
3875
3930
|
}
|
|
3876
|
-
|
|
3931
|
+
/**
|
|
3932
|
+
* Fetch an Emoji from the API or resolves it from the local cache.
|
|
3933
|
+
* @param emoji The ID, mention, or {@link Emoji} object to fetch
|
|
3934
|
+
* @param force Whether to skip the cache check and force a direct API request. Defaults to false.
|
|
3935
|
+
* @returns A promise that resolves to the fetched {@link Emoji} object.
|
|
3936
|
+
* @throws {TypeError} If an invalid {@link EmojiResolvable} is provided.
|
|
3937
|
+
* @throws {Error} If the API request fails.
|
|
3938
|
+
* @example
|
|
3939
|
+
* // Fetch a channel, bypassing cache
|
|
3940
|
+
* const channel = await client.channels.fetch("01H...", true);
|
|
3941
|
+
*/
|
|
3942
|
+
async fetch(emoji, force = false) {
|
|
3943
|
+
if (!force) {
|
|
3944
|
+
const cached = this.resolve(emoji);
|
|
3945
|
+
if (cached) return cached;
|
|
3946
|
+
}
|
|
3947
|
+
const id = this.resolveId(emoji);
|
|
3877
3948
|
const data = await this.client.rest.get(`/custom/emoji/${id}`);
|
|
3878
3949
|
return this._add(data);
|
|
3879
3950
|
}
|
|
3951
|
+
/**
|
|
3952
|
+
* Resolves a {@link EmojiResolvable} to a {@link Emoji} object from the cache.
|
|
3953
|
+
* @param emoji The {@link EmojiResolvable} to resolve.
|
|
3954
|
+
* @returns The resolved {@link Emoji} object, or undefined if not found.
|
|
3955
|
+
*/
|
|
3956
|
+
resolve(emoji) {
|
|
3957
|
+
if (emoji instanceof Emoji) return emoji;
|
|
3958
|
+
if (typeof emoji === "string") {
|
|
3959
|
+
const id = emoji.replace(/[<:>]/g, "");
|
|
3960
|
+
return this.cache.get(id);
|
|
3961
|
+
}
|
|
3962
|
+
return void 0;
|
|
3963
|
+
}
|
|
3964
|
+
/**
|
|
3965
|
+
* Extracts ID from a {@link EmojiResolvable}.
|
|
3966
|
+
* @param emoji The {@link EmojiResolvable} to extract the ID from.
|
|
3967
|
+
* @returns The extracted {@link Emoji} ID.
|
|
3968
|
+
* @throws {TypeError} If an invalid type is provided.
|
|
3969
|
+
*/
|
|
3970
|
+
resolveId(emoji) {
|
|
3971
|
+
if (emoji instanceof Emoji) return emoji.id;
|
|
3972
|
+
if (typeof emoji === "string") {
|
|
3973
|
+
return emoji.replace(/:/g, "");
|
|
3974
|
+
}
|
|
3975
|
+
throw new Error("Invalid EmojiResolvable");
|
|
3976
|
+
}
|
|
3977
|
+
/**
|
|
3978
|
+
* Create a new emoji
|
|
3979
|
+
* @param options The options for creating the emoji
|
|
3980
|
+
* @returns A promise that resolves to the created {@link Emoji} object.
|
|
3981
|
+
* @throws {Error} If no server is registered in the {@link EmojiManager} or if the emoji attachment cannot be resolved.
|
|
3982
|
+
* @example
|
|
3983
|
+
* const emoji = await client.emojis.create(server, { emoji: "path/to/emoji.png", name: "myEmoji" });
|
|
3984
|
+
*/
|
|
3985
|
+
async crate(options) {
|
|
3986
|
+
if (!this.server) throw new Error("No server registered in EmojiManager");
|
|
3987
|
+
const resolvedId = await resolveAttachment(this.client.rest, options.emoji, "emojis");
|
|
3988
|
+
if (!resolvedId) throw new Error("Failed to resolve emoji attachment");
|
|
3989
|
+
const payload = {
|
|
3990
|
+
name: options.name,
|
|
3991
|
+
parent: {
|
|
3992
|
+
type: "Server",
|
|
3993
|
+
id: this.server.id
|
|
3994
|
+
}
|
|
3995
|
+
};
|
|
3996
|
+
if (options.nsfw) payload.nsfw = options.nsfw;
|
|
3997
|
+
const data = await this.client.rest.put(`/custom/emoji/${resolvedId}`, payload);
|
|
3998
|
+
return this._add(data);
|
|
3999
|
+
}
|
|
4000
|
+
/**
|
|
4001
|
+
* Delete an emoji
|
|
4002
|
+
* @param emoji The {@link EmojiResolvable} to delete
|
|
4003
|
+
* @throws {Error} If no server is registered in the {@link EmojiManager}.
|
|
4004
|
+
* @example
|
|
4005
|
+
* await client.emojis.delete(emoji);
|
|
4006
|
+
*/
|
|
4007
|
+
async delete(emoji) {
|
|
4008
|
+
const id = this.resolveId(emoji);
|
|
4009
|
+
await this.client.rest.delete(`/custom/emoji/${id}`);
|
|
4010
|
+
this.cache.delete(id);
|
|
4011
|
+
}
|
|
4012
|
+
/**
|
|
4013
|
+
* Edit an emoji
|
|
4014
|
+
* @param emoji The {@link EmojiResolvable} to edit
|
|
4015
|
+
* @param options The options to edit the emoji with
|
|
4016
|
+
* @returns A promise that resolves to the edited {@link Emoji} object.
|
|
4017
|
+
* @throws {Error} If no server is registered in the {@link EmojiManager}.
|
|
4018
|
+
* @example
|
|
4019
|
+
* const editedEmoji = await client.emojis.edit(emoji, { name: "newName" });
|
|
4020
|
+
*/
|
|
4021
|
+
async edit(emoji, options) {
|
|
4022
|
+
const id = this.resolveId(emoji);
|
|
4023
|
+
const payload = {
|
|
4024
|
+
name: options.name
|
|
4025
|
+
};
|
|
4026
|
+
const data = await this.client.rest.patch(`/custom/emoji/${id}`, payload);
|
|
4027
|
+
return this._add(data);
|
|
4028
|
+
}
|
|
3880
4029
|
[util11.inspect.custom]() {
|
|
3881
4030
|
return this.cache;
|
|
3882
4031
|
}
|
|
@@ -4282,6 +4431,15 @@ var SweeperManager = class {
|
|
|
4282
4431
|
|
|
4283
4432
|
// src/client/Client.ts
|
|
4284
4433
|
var Client = class extends import_events2.EventEmitter {
|
|
4434
|
+
rest;
|
|
4435
|
+
gateway;
|
|
4436
|
+
channels;
|
|
4437
|
+
servers;
|
|
4438
|
+
users;
|
|
4439
|
+
sweepers;
|
|
4440
|
+
emojis;
|
|
4441
|
+
user = null;
|
|
4442
|
+
options;
|
|
4285
4443
|
constructor(options = {}) {
|
|
4286
4444
|
super({ captureRejections: true });
|
|
4287
4445
|
this.options = options;
|
|
@@ -4293,23 +4451,40 @@ var Client = class extends import_events2.EventEmitter {
|
|
|
4293
4451
|
this.emojis = new EmojiManager(this, void 0, options.cacheLimits?.emojis);
|
|
4294
4452
|
this.sweepers = new SweeperManager(this, options.sweepers ?? {});
|
|
4295
4453
|
}
|
|
4296
|
-
rest;
|
|
4297
|
-
gateway;
|
|
4298
|
-
channels;
|
|
4299
|
-
servers;
|
|
4300
|
-
users;
|
|
4301
|
-
sweepers;
|
|
4302
|
-
emojis;
|
|
4303
|
-
user = null;
|
|
4304
4454
|
/**
|
|
4305
4455
|
* Connects the bot to the Stoat Gateway
|
|
4306
4456
|
*/
|
|
4307
4457
|
async login(token) {
|
|
4308
4458
|
if (!token) throw new Error("A valid token must be provided.");
|
|
4309
|
-
this.
|
|
4459
|
+
const rootApiUrl = this.options.apiURL ?? "https://api.stoat.chat";
|
|
4460
|
+
this.rest.setBaseURL(rootApiUrl);
|
|
4310
4461
|
this.rest.setToken(token);
|
|
4462
|
+
const configData = await this.fetchConfig(rootApiUrl);
|
|
4463
|
+
const finalWsUrl = this.options.overrides?.wsURL ?? configData.ws;
|
|
4464
|
+
if (!finalWsUrl) {
|
|
4465
|
+
throw new Error(
|
|
4466
|
+
`[Stoat Misconfiguration] The server at '${rootApiUrl}' is running, but it has no WebSocket URL configured. The server administrator needs to set their gateway config, or you must bypass it using 'options.overrides.wsURL'.`
|
|
4467
|
+
);
|
|
4468
|
+
}
|
|
4469
|
+
this.gateway.setGatewayUrl(finalWsUrl);
|
|
4470
|
+
const finalCdnUrl = this.options.overrides?.cdnURL ?? configData.features.autumn.url;
|
|
4471
|
+
if (!finalCdnUrl) {
|
|
4472
|
+
throw new Error(
|
|
4473
|
+
`[Stoat Misconfiguration] The server at '${rootApiUrl}' is running, but it has no CDN URL configured. The server administrator needs to set their cdn config, or you must bypass it using 'options.overrides.cdnURL'.`
|
|
4474
|
+
);
|
|
4475
|
+
}
|
|
4476
|
+
this.rest.setCDNURL(finalCdnUrl);
|
|
4477
|
+
this.sweepers.start();
|
|
4311
4478
|
return this.gateway.connect(token);
|
|
4312
4479
|
}
|
|
4480
|
+
async fetchConfig(baseURL) {
|
|
4481
|
+
try {
|
|
4482
|
+
const response = await fetch(baseURL);
|
|
4483
|
+
return await response.json();
|
|
4484
|
+
} catch (error) {
|
|
4485
|
+
throw new Error(`Failed to fetch ${baseURL}, make sure the instance is running.`);
|
|
4486
|
+
}
|
|
4487
|
+
}
|
|
4313
4488
|
[/* @__PURE__ */ Symbol.for("nodejs.rejection")](error) {
|
|
4314
4489
|
this.emit("error", error);
|
|
4315
4490
|
}
|