diff --git a/.eslintrc.json b/.eslintrc.json
index c6345fc2..adf289db 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -346,6 +346,7 @@
],
"unicorn/prefer-event-target": "off",
"@typescript-eslint/no-unsafe-declaration-merging": "off",
- "@typescript-eslint/no-unsafe-enum-comparison": "off"
+ "@typescript-eslint/no-unsafe-enum-comparison": "off",
+ "unicorn/prefer-ternary": "off"
}
}
diff --git a/README.md b/README.md
index c74615f3..09639737 100644
--- a/README.md
+++ b/README.md
@@ -48,8 +48,10 @@ The documentation under `dev` is always for the latest commit. If something isn'
### Optional Dependencies
-* `pako` - Compression (gateway)
-* `zlib-sync` - Compression (gateway, faster than pako)
+All compression options are mutually exclusive.
+* `pako` - zlib Compression (gateway)
+* `zlib-sync` - zlib Compression (gateway, faster than pako)
+* `fzstd` - Zstandard Compression (gateway)
* `erlpack` - Encoding (gateway, alternative to JSON)
## Links
diff --git a/lib/gateway/Shard.ts b/lib/gateway/Shard.ts
index 36aca7a6..04e35ade 100644
--- a/lib/gateway/Shard.ts
+++ b/lib/gateway/Shard.ts
@@ -1,5 +1,6 @@
/** @module Shard */
import type ShardManager from "./ShardManager";
+import type Compression from "./compression/base";
import type Client from "../Client";
import TypedEmitter from "../util/TypedEmitter";
import Bucket from "../rest/Bucket";
@@ -23,13 +24,8 @@ import type { ShardEvents } from "../types/events";
import GatewayError, { DependencyError } from "../util/Errors";
import ClientApplication from "../structures/ClientApplication";
import WebSocket, { type Data } from "ws";
-import type Pako from "pako";
-// eslint-disable-next-line @typescript-eslint/ban-ts-comment
-// @ts-ignore
-import type { Inflate } from "zlib-sync";
import { randomBytes } from "node:crypto";
import { inspect } from "node:util";
-import assert from "node:assert";
/* eslint-disable @typescript-eslint/ban-ts-comment, @typescript-eslint/no-redundant-type-constituents, @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment, unicorn/prefer-module, @typescript-eslint/no-unsafe-member-access */
// @ts-ignore
@@ -37,29 +33,17 @@ let Erlpack: typeof import("erlpack") | undefined;
try {
Erlpack = require("erlpack");
} catch {}
-// @ts-ignore
-let ZlibSync: typeof import("pako") | typeof import("zlib-sync") | undefined, zlibConstants: typeof import("pako").constants | typeof import("zlib-sync") | undefined;
-try {
- ZlibSync = require("zlib-sync");
- zlibConstants = require("zlib-sync");
-} catch {
- try {
- ZlibSync = require("pako");
- zlibConstants = require("pako").constants;
- } catch {}
-}
/* eslint-enable @typescript-eslint/ban-ts-comment, @typescript-eslint/no-redundant-type-constituents, @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment, unicorn/prefer-module */
/** Represents a gateway connection to Discord. See {@link ShardEvents | Shard Events} for a list of events. */
export default class Shard extends TypedEmitter {
+ private _compressor: Compression | undefined;
private _connectTimeout: NodeJS.Timeout | null;
private _getAllUsersCount: Record;
private _getAllUsersQueue: Array;
private _guildCreateTimeout: NodeJS.Timeout | null;
private _heartbeatInterval: NodeJS.Timeout | null;
private _requestMembersPromise: Record; received: number; timeout: NodeJS.Timeout; reject(reason?: unknown): void; resolve(value: unknown): void; }>;
- // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
- private _sharedZLib!: Pako.Inflate | Inflate;
client!: Client;
connectAttempts: number;
connecting: boolean;
@@ -156,7 +140,8 @@ export default class Shard extends TypedEmitter {
}
this.resumeURL = `${url}?v=${GATEWAY_VERSION}&encoding=${Erlpack ? "etf" : "json"}`;
if (this.client.shards.options.compress) {
- this.resumeURL += "&compress=zlib-stream";
+ const type = this.client.shards.options.compress === "zstd-stream" ? "zstd-stream" : "zlib-stream";
+ this.resumeURL += `&compress=${type}`;
}
this.sessionID = data.session_id;
@@ -221,12 +206,34 @@ export default class Shard extends TypedEmitter {
}
this.status = "connecting";
if (this.client.shards.options.compress) {
- if (!ZlibSync) {
- throw new DependencyError("Cannot use compression without pako or zlib-sync.");
+ const type = this.client.shards.options.compress;
+ /* eslint-disable @typescript-eslint/no-var-requires, unicorn/prefer-module */
+ if (type === "zstd-stream") {
+ if (!this.client.util._isModuleInstalled("fzstd")) {
+ throw new DependencyError("Cannot use zstd based compression without fzstd.");
+ }
+ this.client.emit("debug", "Initializing zstd-based compression with fzstd.");
+ const ZstdCompression = (require(`${__dirname}/compression/zstd`) as { default: new(shard: Shard) => Compression; }).default;
+ this._compressor = new ZstdCompression(this);
+ } else if (type === "zlib-stream") {
+ const hasZlibSync = this.client.util._isModuleInstalled("zlib-sync");
+ const hasPako = this.client.util._isModuleInstalled("pako");
+
+ if (hasZlibSync) {
+ this.client.emit("debug", "Initializing zlib-based compression with zlib-sync.");
+ const ZlibSyncCompression = (require(`${__dirname}/compression/zlib-sync`) as { default: new(shard: Shard) => Compression; }).default;
+ this._compressor = new ZlibSyncCompression(this);
+ } else if (hasPako) {
+ this.client.emit("debug", "Initializing zlib-based compression with pako.");
+ const PakoCompression = (require(`${__dirname}/compression/pako`) as { default: new(shard: Shard) => Compression; }).default;
+ this._compressor = new PakoCompression(this);
+ } else {
+ throw new DependencyError("Cannot use zlib based compression without pako or zlib-sync.");
+ }
+ } else {
+ throw new TypeError(`Invalid compression type "${type as string}".`);
}
- this.client.emit("debug", "Initializing zlib-sync-based compression.");
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
- this._sharedZLib = new ZlibSync.Inflate({ chunkSize: 128 * 1024 });
+ /* eslint-enable @typescript-eslint/no-var-requires, unicorn/prefer-module */
}
if (!this.client.shards.options.override.gatewayURLIsResumeURL && this.sessionID) {
if (this.resumeURL === null) {
@@ -443,7 +450,7 @@ export default class Shard extends TypedEmitter {
}
/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-argument */
- private onWSMessage(data: Data): void {
+ private async onWSMessage(data: Data): Promise {
if (typeof data === "string") {
data = Buffer.from(data);
}
@@ -457,54 +464,28 @@ export default class Shard extends TypedEmitter {
data = Buffer.concat(data);
}
- const is = (input: unknown): input is T => true;
- assert(is(data));
+ const buf = data as Buffer;
if (this.client.shards.options.compress) {
- if (data.length >= 4 && data.readUInt32BE(data.length - 4) === 0xFFFF) {
- // store the current pointer for slicing buffers after pushing.
- const currentPointer: number | undefined = this._sharedZLib.strm?.next_out;
- this._sharedZLib.push(data, zlibConstants!.Z_SYNC_FLUSH);
- if (this._sharedZLib.err) {
- this.client.emit("error", new GatewayError(`zlib error ${this._sharedZLib.err}: ${this._sharedZLib.msg ?? ""}`, 0));
- return;
- }
-
- if (currentPointer === undefined) {
- // decompression support by zlib-sync
- data = Buffer.from(this._sharedZLib.result ?? "");
- } else if (this._sharedZLib.chunks.length === 0) {
- // decompression support by pako. The current buffer hasn't been flushed
- data = Buffer.from(this._sharedZLib.strm!.output.slice(currentPointer));
- } else {
- // decompression support by pako. Buffers have been flushed once or more times.
- data = Buffer.concat([
- this._sharedZLib.chunks[0].slice(currentPointer),
- ...this._sharedZLib.chunks.slice(1),
- this._sharedZLib.strm.output
- ]);
- this._sharedZLib.chunks = [];
- }
-
- assert(is(data));
+ let result = await this._compressor!.decompress(buf);
+ if (result === null) {
+ return;
+ }
- if (Erlpack) {
- return this.onPacket(Erlpack.unpack(data as Buffer) as AnyReceivePacket);
- } else {
- // After the valid data, all the remaining octets are filled with zero, so remove them.
- let last = data.length - 1;
- if (data[last] === 0) {
- while (data[last - 1] === 0 && last > 0) last--;
- data = data.subarray(0, last);
- }
- return this.onPacket(JSON.parse(String(data)) as AnyReceivePacket);
- }
+ if (Erlpack) {
+ return this.onPacket(Erlpack.unpack(result) as AnyReceivePacket);
} else {
- this._sharedZLib.push(data, false);
+ // After the valid data, all the remaining octets are filled with zero, so remove them.
+ let last = result.length - 1;
+ if (result[last] === 0) {
+ while (result[last - 1] === 0 && last > 0) last--;
+ result = result.subarray(0, last);
+ }
+ return this.onPacket(JSON.parse(String(result)) as AnyReceivePacket);
}
} else if (Erlpack) {
- return this.onPacket(Erlpack.unpack(data) as AnyReceivePacket);
+ return this.onPacket(Erlpack.unpack(buf) as AnyReceivePacket);
} else {
- return this.onPacket(JSON.parse(data.toString()) as AnyReceivePacket);
+ return this.onPacket(JSON.parse(String(buf)) as AnyReceivePacket);
}
} catch (err) {
this.client.emit("error", err as Error, this.id);
@@ -776,7 +757,7 @@ export default class Shard extends TypedEmitter {
const func = (): void => {
if (++i >= waitFor && this.ws && this.ws.readyState === WebSocket.OPEN) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
- const d: string = Erlpack ? Erlpack.pack({ op, d: data }) : JSON.stringify({ op, d: data });
+ const d: string | Buffer = Erlpack ? Erlpack.pack({ op, d: data }) : JSON.stringify({ op, d: data });
this.ws.send(d);
if (typeof data === "object" && data && "token" in data) {
(data as { token: string; }).token = "[REMOVED]";
diff --git a/lib/gateway/ShardManager.ts b/lib/gateway/ShardManager.ts
index e651c75f..13fcb8e5 100644
--- a/lib/gateway/ShardManager.ts
+++ b/lib/gateway/ShardManager.ts
@@ -22,6 +22,7 @@ try {
/* eslint-enable @typescript-eslint/ban-ts-comment, @typescript-eslint/no-redundant-type-constituents, @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment, unicorn/prefer-module */
+let __compressionTrueDeprecationWarning = 0;
/** A manager for all the client's shards. */
export default class ShardManager extends Collection {
private _buckets: Record;
@@ -39,7 +40,7 @@ export default class ShardManager extends Collection {
this._connectTimeout = null;
this.options = {
autoReconnect: options.autoReconnect ?? true,
- compress: options.compress ?? false,
+ compress: options.compress === true ? (__compressionTrueDeprecationWarning++, "zlib-stream") : options.compress ?? false,
connectionProperties: {
browser: options.connectionProperties?.browser ?? "Oceanic",
device: options.connectionProperties?.device ?? "Oceanic",
@@ -77,6 +78,11 @@ export default class ShardManager extends Collection {
shardIDs: options.shardIDs ?? [],
ws: options.ws ?? {}
};
+ if (__compressionTrueDeprecationWarning === 1) {
+ process.emitWarning("Using `compress: true` is deprecated and will be removed in a future version. Please use `compress: \"zlib-stream\"` instead.", {
+ code: "OCEANIC_GATEWAY_COMPRESSION_TRUE_DEPRECATION"
+ });
+ }
this.options.override.appendQuery ??= (this.options.override.getBot === undefined && this.options.override.url === undefined);
this.options.override.gatewayURLIsResumeURL ??= (this.options.override.getBot !== undefined || this.options.override.url !== undefined);
this.options.override.timeBetweenShardConnects ??= 5000;
@@ -214,7 +220,8 @@ export default class ShardManager extends Collection {
if (url && this.options.override.appendQuery) {
url += `?v=${GATEWAY_VERSION}&encoding=${Erlpack ? "etf" : "json"}`;
if (this.options.compress) {
- url += "&compress=zlib-stream";
+ const type = this.options.compress === "zstd-stream" ? "zstd-stream" : "zlib-stream";
+ url += `&compress=${type}`;
}
this._gatewayURL = url;
}
diff --git a/lib/gateway/compression/base.ts b/lib/gateway/compression/base.ts
new file mode 100644
index 00000000..a20cc940
--- /dev/null
+++ b/lib/gateway/compression/base.ts
@@ -0,0 +1,14 @@
+import type Shard from "../Shard";
+
+export default abstract class Compression {
+ shard!: Shard;
+ abstract decompress(data: Buffer): Promise;
+ constructor(shard: Shard) {
+ Object.defineProperty(this, "shard", {
+ value: shard,
+ configurable: false,
+ enumerable: false,
+ writable: false
+ });
+ }
+}
diff --git a/lib/gateway/compression/pako.ts b/lib/gateway/compression/pako.ts
new file mode 100644
index 00000000..f1f03dd8
--- /dev/null
+++ b/lib/gateway/compression/pako.ts
@@ -0,0 +1,50 @@
+import Compression from "./base";
+import type Shard from "../Shard";
+import GatewayError from "../../util/Errors";
+import { Inflate, constants } from "pako";
+
+interface PakoExtra {
+ chunks: Array;
+ strm: {
+ next_out: number;
+ output: Buffer;
+ };
+}
+
+export default class PakoCompression extends Compression {
+ _sharedZLib: Inflate & PakoExtra;
+ constructor(shard: Shard) {
+ super(shard);
+ this._sharedZLib = new Inflate({ chunkSize: 128 * 1024 }) as Inflate & PakoExtra;
+ }
+
+ async decompress(data: Buffer): Promise {
+ if (data.length >= 4 && data.readUInt32BE(data.length - 4) === 0xFFFF) {
+ // store the current pointer for slicing buffers after pushing.
+ const currentPointer: number | undefined = this._sharedZLib.strm?.next_out;
+ this._sharedZLib.push(data, constants.Z_SYNC_FLUSH);
+ if (this._sharedZLib.err) {
+ this.shard.client.emit("error", new GatewayError(`zlib error ${this._sharedZLib.err}: ${this._sharedZLib.msg ?? ""}`, 0));
+ return null;
+ }
+
+ if (this._sharedZLib.chunks.length === 0) {
+ // The current buffer hasn't been flushed
+ data = Buffer.from(this._sharedZLib.strm!.output.slice(currentPointer));
+ } else {
+ // Buffers have been flushed one or more times
+ data = Buffer.concat([
+ this._sharedZLib.chunks[0].slice(currentPointer),
+ ...this._sharedZLib.chunks.slice(1),
+ this._sharedZLib.strm.output
+ ]);
+ this._sharedZLib.chunks = [];
+ }
+
+ return data;
+ } else {
+ this._sharedZLib.push(data, false);
+ return null;
+ }
+ }
+}
diff --git a/lib/gateway/compression/zlib-sync.ts b/lib/gateway/compression/zlib-sync.ts
new file mode 100644
index 00000000..008b7f66
--- /dev/null
+++ b/lib/gateway/compression/zlib-sync.ts
@@ -0,0 +1,30 @@
+import Compression from "./base";
+import type Shard from "../Shard";
+import GatewayError from "../../util/Errors";
+import ZlibSync from "zlib-sync";
+
+export default class ZlibSyncCompression extends Compression {
+ _sharedZLib: ZlibSync.Inflate;
+ constructor(shard: Shard) {
+ super(shard);
+ this._sharedZLib = new ZlibSync.Inflate({ chunkSize: 128 * 1024 });
+ }
+
+ async decompress(data: Buffer): Promise {
+ if (data.length >= 4 && data.readUInt32BE(data.length - 4) === 0xFFFF) {
+ // store the current pointer for slicing buffers after pushing.
+ this._sharedZLib.push(data, ZlibSync.Z_SYNC_FLUSH);
+ if (this._sharedZLib.err) {
+ this.shard.client.emit("error", new GatewayError(`zlib error ${this._sharedZLib.err}: ${this._sharedZLib.msg ?? ""}`, 0));
+ return null;
+ }
+
+ data = Buffer.from(this._sharedZLib.result ?? "");
+
+ return data;
+ } else {
+ this._sharedZLib.push(data, false);
+ return null;
+ }
+ }
+}
diff --git a/lib/gateway/compression/zstd.ts b/lib/gateway/compression/zstd.ts
new file mode 100644
index 00000000..5e20360a
--- /dev/null
+++ b/lib/gateway/compression/zstd.ts
@@ -0,0 +1,27 @@
+import Compression from "./base";
+import type Shard from "../Shard";
+import fzstd from "fzstd";
+
+export default class ZstdCompression extends Compression {
+ _resolvePromise?: (data: Uint8Array) => void;
+ _resultPromise?: Promise;
+ stream: fzstd.Decompress;
+ constructor(shard: Shard) {
+ super(shard);
+ this.stream = new fzstd.Decompress(data => {
+ this._resolvePromise!(data);
+ });
+ }
+
+ async decompress(data: Buffer): Promise {
+ if (this._resultPromise) {
+ await this._resultPromise;
+ }
+ this._resultPromise = new Promise(resolve => {
+ this._resolvePromise = resolve;
+ });
+ this.stream.push(data);
+ const result = await this._resultPromise;
+ return Buffer.from(result);
+ }
+}
diff --git a/lib/types/gateway.d.ts b/lib/types/gateway.d.ts
index 84b4a34a..32226c80 100644
--- a/lib/types/gateway.d.ts
+++ b/lib/types/gateway.d.ts
@@ -26,9 +26,10 @@ interface GatewayOptions {
autoReconnect?: boolean;
/**
* If packets to and from Discord should be compressed.
+ * @note `true` is the same as `zlib-stream`. This behavior is deprecated.
* @defaultValue false
*/
- compress?: boolean;
+ compress?: boolean | "zlib-stream" | "zstd-stream";
/**
* The concurrency for shard connections. If you don't know what this is, don't mess with it. Only bots in >150,000 servers can use any non-default value.
* @defaultValue 1
@@ -131,6 +132,7 @@ interface GatewayOptions {
*/
seedVoiceConnections?: boolean;
/**
+ * An array of shard IDs to run for this client. Mutually exclusive with `firstShardID` & `lastShardID`.
* An array of shard IDs to run for this client. Mutually exclusive with `firstShardID` & `lastShardID`.
* @defaultValue based on `firstShardID` & `lastShardID`
*/
@@ -163,7 +165,8 @@ export interface OverrideOptions {
url?(shard: Shard, totalShards: number): Promise;
}
-export interface ShardManagerInstanceOptions extends Required> {
+export interface ShardManagerInstanceOptions extends Required> {
+ compress: false | "zlib-stream" | "zstd-stream";
concurrency: number;
connectionProperties: Required;
dispatcher: DispatcherInstanceOptions;
diff --git a/lib/util/Util.ts b/lib/util/Util.ts
index 3765fcca..90618562 100644
--- a/lib/util/Util.ts
+++ b/lib/util/Util.ts
@@ -118,6 +118,17 @@ export default class Util {
return (id === undefined ? undefined : opt[id]) ?? opt.default ?? Infinity;
}
+ /** @hidden intended for internal use only */
+ _isModuleInstalled(name: string): boolean {
+ try {
+ // eslint-disable-next-line unicorn/prefer-module
+ require(name);
+ return true;
+ } catch {
+ return false;
+ }
+ }
+
_setLimit(values?: Record | number, defaultValue = Infinity): Record | number {
if (values === undefined) {
return defaultValue;
diff --git a/package.json b/package.json
index bb145642..82c34e7b 100644
--- a/package.json
+++ b/package.json
@@ -49,6 +49,7 @@
"@types/ws": "^8.5.10",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^6.21.0",
+ "erlpack": "^0.1.4",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-import-newlines": "^1.4.0",
@@ -57,13 +58,16 @@
"eslint-plugin-prefer-arrow": "^1.2.3",
"eslint-plugin-unicorn": "^53.0.0",
"eslint-plugin-unused-imports": "^3.2.0",
+ "fzstd": "^0.1.1",
+ "pako": "^2.1.0",
"rimraf": "^5.0.5",
"typedoc": "0.25.13",
"typedoc-plugin-extras": "3.0.0",
"typedoc-plugin-mdn-links": "^3.1.19",
"typedoc-plugin-merge-modules": "^5.1.0",
"typescript": "^5.3.3",
- "undici-types": "~6.9.0"
+ "undici-types": "~6.9.0",
+ "zlib-sync": "^0.1.9"
},
"dependencies": {
"tslib": "^2.6.2",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 239c34d7..729e60cc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -45,6 +45,9 @@ importers:
'@typescript-eslint/parser':
specifier: ^6.21.0
version: 6.21.0(eslint@8.57.0)(typescript@5.3.3)
+ erlpack:
+ specifier: ^0.1.4
+ version: 0.1.4
eslint:
specifier: ^8.57.0
version: 8.57.0
@@ -69,6 +72,12 @@ importers:
eslint-plugin-unused-imports:
specifier: ^3.2.0
version: 3.2.0(@typescript-eslint/eslint-plugin@7.0.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)
+ fzstd:
+ specifier: ^0.1.1
+ version: 0.1.1
+ pako:
+ specifier: ^2.1.0
+ version: 2.1.0
rimraf:
specifier: ^5.0.5
version: 5.0.5
@@ -90,6 +99,9 @@ importers:
undici-types:
specifier: ~6.9.0
version: 6.9.0
+ zlib-sync:
+ specifier: ^0.1.9
+ version: 0.1.9
packages:
@@ -399,6 +411,9 @@ packages:
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ bindings@1.5.0:
+ resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
+
brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
@@ -554,6 +569,9 @@ packages:
encoding@0.1.13:
resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==}
+ erlpack@0.1.4:
+ resolution: {integrity: sha512-CJYbkEvsB5FqCCu2tLxF1eYKi28PvemC12oqzJ9oO6mDFrFO9G9G7nNJUHhiAyyL9zfXTOJx/tOcrQk+ncD65w==}
+
err-code@2.0.3:
resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==}
@@ -724,6 +742,9 @@ packages:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0}
+ file-uri-to-path@1.0.0:
+ resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==}
+
fill-range@7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
@@ -771,6 +792,9 @@ packages:
functions-have-names@1.2.3:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ fzstd@0.1.1:
+ resolution: {integrity: sha512-dkuVSOKKwh3eas5VkJy1AW1vFpet8TA/fGmVA5krThl8YcOVE/8ZIoEA1+U1vEn5ckxxhLirSdY837azmbaNHA==}
+
get-intrinsic@1.2.2:
resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==}
@@ -1154,6 +1178,9 @@ packages:
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ nan@2.20.0:
+ resolution: {integrity: sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==}
+
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
@@ -1237,6 +1264,9 @@ packages:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
+ pako@2.1.0:
+ resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
+
parent-module@1.0.1:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
@@ -1689,6 +1719,9 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
+ zlib-sync@0.1.9:
+ resolution: {integrity: sha512-DinB43xCjVwIBDpaIvQqHbmDsnYnSt6HJ/yiB2MZQGTqgPcwBSZqLkimXwK8BvdjQ/MaZysb5uEenImncqvCqQ==}
+
snapshots:
'@aashutoshrathi/word-wrap@1.2.6': {}
@@ -2077,6 +2110,10 @@ snapshots:
balanced-match@1.0.2: {}
+ bindings@1.5.0:
+ dependencies:
+ file-uri-to-path: 1.0.0
+
brace-expansion@1.1.11:
dependencies:
balanced-match: 1.0.2
@@ -2235,6 +2272,11 @@ snapshots:
iconv-lite: 0.6.3
optional: true
+ erlpack@0.1.4:
+ dependencies:
+ bindings: 1.5.0
+ nan: 2.20.0
+
err-code@2.0.3: {}
error-ex@1.3.2:
@@ -2506,6 +2548,8 @@ snapshots:
dependencies:
flat-cache: 3.2.0
+ file-uri-to-path@1.0.0: {}
+
fill-range@7.0.1:
dependencies:
to-regex-range: 5.0.1
@@ -2558,6 +2602,8 @@ snapshots:
functions-have-names@1.2.3: {}
+ fzstd@0.1.1: {}
+
get-intrinsic@1.2.2:
dependencies:
function-bind: 1.1.2
@@ -2936,6 +2982,8 @@ snapshots:
ms@2.1.3: {}
+ nan@2.20.0: {}
+
natural-compare@1.4.0: {}
negotiator@0.6.3: {}
@@ -3039,6 +3087,8 @@ snapshots:
p-try@2.2.0: {}
+ pako@2.1.0: {}
+
parent-module@1.0.1:
dependencies:
callsites: 3.1.0
@@ -3485,3 +3535,7 @@ snapshots:
yallist@4.0.0: {}
yocto-queue@0.1.0: {}
+
+ zlib-sync@0.1.9:
+ dependencies:
+ nan: 2.20.0