@weapp-vite/miniprogram-automator 1.2.3 → 1.2.5
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/dist/index.d.mts +7 -3
- package/dist/index.mjs +52 -10
- package/dist/{launch-2X75zDRY.mjs → launch-mRKloPOa.mjs} +26 -26
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -54,7 +54,7 @@ declare class Connection extends EventEmitter {
|
|
|
54
54
|
dispose(): void;
|
|
55
55
|
private onMessage;
|
|
56
56
|
private onClose;
|
|
57
|
-
static create(url: string): Promise<Connection>;
|
|
57
|
+
static create(url: string, timeout?: number): Promise<Connection>;
|
|
58
58
|
}
|
|
59
59
|
//#endregion
|
|
60
60
|
//#region src/Native.d.ts
|
|
@@ -232,6 +232,7 @@ declare class Page {
|
|
|
232
232
|
//#region src/MiniProgram.d.ts
|
|
233
233
|
interface IScreenshotOptions {
|
|
234
234
|
path?: string;
|
|
235
|
+
timeout?: number;
|
|
235
236
|
}
|
|
236
237
|
interface IAuditsOptions {
|
|
237
238
|
path?: string;
|
|
@@ -251,6 +252,7 @@ interface CurrentPageOptions {
|
|
|
251
252
|
declare class MiniProgram extends EventEmitter {
|
|
252
253
|
private connection;
|
|
253
254
|
private appBindings;
|
|
255
|
+
private logEnabled;
|
|
254
256
|
private pageMap;
|
|
255
257
|
private nativeIns?;
|
|
256
258
|
constructor(connection: Connection);
|
|
@@ -274,6 +276,7 @@ declare class MiniProgram extends EventEmitter {
|
|
|
274
276
|
close(): Promise<void>;
|
|
275
277
|
remote(auto?: boolean): Promise<void>;
|
|
276
278
|
disconnect(): void;
|
|
279
|
+
enableLog(): Promise<void>;
|
|
277
280
|
on(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
278
281
|
exposeFunction(name: string, bindingFunction: AutomatorCallable): Promise<void>;
|
|
279
282
|
checkVersion(): Promise<void>;
|
|
@@ -281,7 +284,7 @@ declare class MiniProgram extends EventEmitter {
|
|
|
281
284
|
* @description 等待小程序 App 域协议可用,避免返回半就绪自动化会话。
|
|
282
285
|
*/
|
|
283
286
|
waitForAppReady(timeout?: number): Promise<void>;
|
|
284
|
-
screenshot(options?: IScreenshotOptions): Promise<
|
|
287
|
+
screenshot(options?: IScreenshotOptions): Promise<string | undefined>;
|
|
285
288
|
testAccounts(): Promise<any>;
|
|
286
289
|
/**
|
|
287
290
|
* @description 获取开发者工具 Tool 域基础信息。
|
|
@@ -413,7 +416,7 @@ declare class SmartappApp {
|
|
|
413
416
|
retry?: number;
|
|
414
417
|
timeout?: number;
|
|
415
418
|
}): Promise<SmartappPage>;
|
|
416
|
-
screenshot(options?: ScreenshotOptions): Promise<
|
|
419
|
+
screenshot(options?: ScreenshotOptions): Promise<string | undefined>;
|
|
417
420
|
currentPage(): Promise<SmartappPage>;
|
|
418
421
|
data(): Promise<any>;
|
|
419
422
|
tabs(): Promise<never[]>;
|
|
@@ -488,6 +491,7 @@ declare function normalizePlatform(platform?: MiniprogramAutomatorPlatform): Nor
|
|
|
488
491
|
//#region src/Launcher.d.ts
|
|
489
492
|
interface IConnectOptions {
|
|
490
493
|
wsEndpoint: string;
|
|
494
|
+
timeout?: number;
|
|
491
495
|
platform?: MiniprogramAutomatorPlatform;
|
|
492
496
|
}
|
|
493
497
|
/** ILaunchOptions 的类型定义。 */
|
package/dist/index.mjs
CHANGED
|
@@ -503,6 +503,7 @@ var Transport = class extends EventEmitter {
|
|
|
503
503
|
const debugProtocol = createDebug("automator:protocol");
|
|
504
504
|
const closeErrTip = "Connection closed, check if wechat web devTools is still running";
|
|
505
505
|
const REQUEST_TIMEOUT = 3e4;
|
|
506
|
+
const CONNECT_TIMEOUT = 3e4;
|
|
506
507
|
/** Connection 的实现。 */
|
|
507
508
|
var Connection = class Connection extends EventEmitter {
|
|
508
509
|
transport;
|
|
@@ -571,20 +572,35 @@ var Connection = class Connection extends EventEmitter {
|
|
|
571
572
|
}
|
|
572
573
|
this.callbacks.clear();
|
|
573
574
|
};
|
|
574
|
-
static create(url) {
|
|
575
|
+
static create(url, timeout = CONNECT_TIMEOUT) {
|
|
575
576
|
return new Promise((resolve, reject) => {
|
|
576
577
|
const ws = new WebSocket(url);
|
|
578
|
+
let settled = false;
|
|
579
|
+
const timer = setTimeout(() => {
|
|
580
|
+
if (settled) return;
|
|
581
|
+
settled = true;
|
|
582
|
+
ws.close();
|
|
583
|
+
reject(/* @__PURE__ */ new Error(`Timed out connecting to DevTools websocket ${url} after ${timeout}ms`));
|
|
584
|
+
}, timeout);
|
|
577
585
|
ws.on("open", () => {
|
|
586
|
+
if (settled) return;
|
|
587
|
+
settled = true;
|
|
588
|
+
clearTimeout(timer);
|
|
578
589
|
resolve(new Connection(new Transport(ws)));
|
|
579
590
|
});
|
|
580
|
-
ws.on("error",
|
|
591
|
+
ws.on("error", (error) => {
|
|
592
|
+
if (settled) return;
|
|
593
|
+
settled = true;
|
|
594
|
+
clearTimeout(timer);
|
|
595
|
+
reject(error);
|
|
596
|
+
});
|
|
581
597
|
});
|
|
582
598
|
}
|
|
583
599
|
};
|
|
584
600
|
//#endregion
|
|
585
601
|
//#region src/headless.ts
|
|
586
602
|
async function launchHeadlessAutomator(options) {
|
|
587
|
-
return await (await import("./launch-
|
|
603
|
+
return await (await import("./launch-mRKloPOa.mjs")).launch({ projectPath: options.projectPath });
|
|
588
604
|
}
|
|
589
605
|
//#endregion
|
|
590
606
|
//#region src/launcher/portLease.ts
|
|
@@ -683,7 +699,7 @@ async function acquireAutomatorPortLease(preferredPort) {
|
|
|
683
699
|
}
|
|
684
700
|
//#endregion
|
|
685
701
|
//#region package.json
|
|
686
|
-
var version = "1.2.
|
|
702
|
+
var version = "1.2.5";
|
|
687
703
|
//#endregion
|
|
688
704
|
//#region src/Native.ts
|
|
689
705
|
/** Native 的实现。 */
|
|
@@ -885,6 +901,8 @@ const CHANGE_ROUTE_POLL_DELAY = 500;
|
|
|
885
901
|
const APP_READY_TIMEOUT = 2e4;
|
|
886
902
|
const APP_READY_PROBE_TIMEOUT = 3e3;
|
|
887
903
|
const APP_READY_POLL_DELAY = 500;
|
|
904
|
+
const SCREENSHOT_RETRIES = 2;
|
|
905
|
+
const SCREENSHOT_RETRY_DELAY = 500;
|
|
888
906
|
const CHANGE_ROUTE_DEBUG_ENABLED = process.env.WEAPP_VITE_E2E_CHANGE_ROUTE_DEBUG === "1";
|
|
889
907
|
function sleep(ms) {
|
|
890
908
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -920,6 +938,11 @@ function isPageStackProtocolTimeout(error) {
|
|
|
920
938
|
function isCallWxMethodProtocolTimeout(error) {
|
|
921
939
|
return error instanceof Error && "code" in error && error.code === "DEVTOOLS_PROTOCOL_TIMEOUT" && "method" in error && error.method === "App.callWxMethod";
|
|
922
940
|
}
|
|
941
|
+
function isCaptureScreenshotRecoverableError(error) {
|
|
942
|
+
if (!(error instanceof Error)) return false;
|
|
943
|
+
if ("code" in error && error.code === "DEVTOOLS_PROTOCOL_TIMEOUT" && "method" in error && error.method === "App.captureScreenshot") return true;
|
|
944
|
+
return error.message.includes("fail to capture screenshot") || error.message.includes("App.captureScreenshot");
|
|
945
|
+
}
|
|
923
946
|
function isRouteContextProbeError(error) {
|
|
924
947
|
return isCurrentPageProtocolTimeout(error) || isPageStackProtocolTimeout(error);
|
|
925
948
|
}
|
|
@@ -934,6 +957,7 @@ function logChangeRouteDebug(message) {
|
|
|
934
957
|
var MiniProgram = class extends EventEmitter {
|
|
935
958
|
connection;
|
|
936
959
|
appBindings = /* @__PURE__ */ new Map();
|
|
960
|
+
logEnabled = false;
|
|
937
961
|
pageMap = /* @__PURE__ */ new Map();
|
|
938
962
|
nativeIns;
|
|
939
963
|
constructor(connection) {
|
|
@@ -1098,8 +1122,12 @@ var MiniProgram = class extends EventEmitter {
|
|
|
1098
1122
|
disconnect() {
|
|
1099
1123
|
this.connection.dispose();
|
|
1100
1124
|
}
|
|
1125
|
+
async enableLog() {
|
|
1126
|
+
await this.send("App.enableLog");
|
|
1127
|
+
this.logEnabled = true;
|
|
1128
|
+
}
|
|
1101
1129
|
on(event, listener) {
|
|
1102
|
-
if (event === "console") this.
|
|
1130
|
+
if (event === "console" && !this.logEnabled) this.enableLog().catch(() => {});
|
|
1103
1131
|
super.on(event, listener);
|
|
1104
1132
|
return this;
|
|
1105
1133
|
}
|
|
@@ -1128,9 +1156,20 @@ var MiniProgram = class extends EventEmitter {
|
|
|
1128
1156
|
throw lastError instanceof Error ? lastError : /* @__PURE__ */ new Error(`Timed out waiting App domain readiness after ${timeout}ms`);
|
|
1129
1157
|
}
|
|
1130
1158
|
async screenshot(options = {}) {
|
|
1131
|
-
const {
|
|
1132
|
-
|
|
1133
|
-
|
|
1159
|
+
const sendOptions = options.timeout ? { timeout: options.timeout } : void 0;
|
|
1160
|
+
let lastError;
|
|
1161
|
+
let data;
|
|
1162
|
+
for (let attempt = 1; attempt <= SCREENSHOT_RETRIES; attempt += 1) try {
|
|
1163
|
+
data = (await this.send("App.captureScreenshot", {}, sendOptions)).data;
|
|
1164
|
+
if (!options.path) return data;
|
|
1165
|
+
await fs.writeFile(options.path, data, "base64");
|
|
1166
|
+
return;
|
|
1167
|
+
} catch (error) {
|
|
1168
|
+
lastError = error;
|
|
1169
|
+
if (!isCaptureScreenshotRecoverableError(error) || attempt === SCREENSHOT_RETRIES) throw error;
|
|
1170
|
+
await sleep(SCREENSHOT_RETRY_DELAY);
|
|
1171
|
+
}
|
|
1172
|
+
throw lastError;
|
|
1134
1173
|
}
|
|
1135
1174
|
async testAccounts() {
|
|
1136
1175
|
return (await this.send("Tool.getTestAccounts")).accounts;
|
|
@@ -1860,7 +1899,10 @@ var Launcher = class {
|
|
|
1860
1899
|
await waitUntil(async () => {
|
|
1861
1900
|
try {
|
|
1862
1901
|
if (processError) return true;
|
|
1863
|
-
const candidate = await this.connectTool({
|
|
1902
|
+
const candidate = await this.connectTool({
|
|
1903
|
+
timeout: 3e3,
|
|
1904
|
+
wsEndpoint: `ws://127.0.0.1:${port}`
|
|
1905
|
+
});
|
|
1864
1906
|
try {
|
|
1865
1907
|
await candidate.checkVersion();
|
|
1866
1908
|
if (typeof candidate.waitForAppReady === "function") await candidate.waitForAppReady(timeout);
|
|
@@ -1912,7 +1954,7 @@ var Launcher = class {
|
|
|
1912
1954
|
}
|
|
1913
1955
|
async connectTool(options) {
|
|
1914
1956
|
try {
|
|
1915
|
-
return new MiniProgram(await Connection.create(options.wsEndpoint));
|
|
1957
|
+
return new MiniProgram(await Connection.create(options.wsEndpoint, options.timeout));
|
|
1916
1958
|
} catch {
|
|
1917
1959
|
throw new Error(`Failed connecting to ${options.wsEndpoint}, check if target project window is opened with automation enabled`);
|
|
1918
1960
|
}
|
|
@@ -437,7 +437,7 @@ function createPageInstance(route, definition, options = {}, pageState = {}) {
|
|
|
437
437
|
}
|
|
438
438
|
//#endregion
|
|
439
439
|
//#region ../../node_modules/.pnpm/entities@8.0.0/node_modules/entities/dist/decode-codepoint.js
|
|
440
|
-
const decodeMap = new Map([
|
|
440
|
+
const decodeMap = /* @__PURE__ */ new Map([
|
|
441
441
|
[0, 65533],
|
|
442
442
|
[128, 8364],
|
|
443
443
|
[130, 8218],
|
|
@@ -952,7 +952,7 @@ var QuoteType;
|
|
|
952
952
|
* sequences with an increased offset.
|
|
953
953
|
*/
|
|
954
954
|
const Sequences = {
|
|
955
|
-
Empty: new Uint8Array(0),
|
|
955
|
+
Empty: /* @__PURE__ */ new Uint8Array(0),
|
|
956
956
|
Cdata: new Uint8Array([
|
|
957
957
|
67,
|
|
958
958
|
68,
|
|
@@ -1081,7 +1081,7 @@ const Sequences = {
|
|
|
1081
1081
|
* where index 2 is the first tag-name character, so matching always
|
|
1082
1082
|
* continues from offset 3.
|
|
1083
1083
|
*/
|
|
1084
|
-
const specialStartSequences = new Map([
|
|
1084
|
+
const specialStartSequences = /* @__PURE__ */ new Map([
|
|
1085
1085
|
[Sequences.IframeEnd[2], Sequences.IframeEnd],
|
|
1086
1086
|
[Sequences.NoembedEnd[2], Sequences.NoembedEnd],
|
|
1087
1087
|
[Sequences.Plaintext[2], Sequences.Plaintext],
|
|
@@ -1773,7 +1773,7 @@ var Tokenizer = class {
|
|
|
1773
1773
|
//#endregion
|
|
1774
1774
|
//#region ../../node_modules/.pnpm/htmlparser2@12.0.0/node_modules/htmlparser2/dist/Parser.js
|
|
1775
1775
|
const { fromCodePoint } = String;
|
|
1776
|
-
const formTags = new Set([
|
|
1776
|
+
const formTags = /* @__PURE__ */ new Set([
|
|
1777
1777
|
"input",
|
|
1778
1778
|
"option",
|
|
1779
1779
|
"optgroup",
|
|
@@ -1782,8 +1782,8 @@ const formTags = new Set([
|
|
|
1782
1782
|
"datalist",
|
|
1783
1783
|
"textarea"
|
|
1784
1784
|
]);
|
|
1785
|
-
const pTag = new Set(["p"]);
|
|
1786
|
-
const headingTags = new Set([
|
|
1785
|
+
const pTag = /* @__PURE__ */ new Set(["p"]);
|
|
1786
|
+
const headingTags = /* @__PURE__ */ new Set([
|
|
1787
1787
|
"h1",
|
|
1788
1788
|
"h2",
|
|
1789
1789
|
"h3",
|
|
@@ -1792,28 +1792,28 @@ const headingTags = new Set([
|
|
|
1792
1792
|
"h6",
|
|
1793
1793
|
"p"
|
|
1794
1794
|
]);
|
|
1795
|
-
const tableSectionTags = new Set(["thead", "tbody"]);
|
|
1796
|
-
const ddtTags = new Set(["dd", "dt"]);
|
|
1797
|
-
const rtpTags = new Set(["rt", "rp"]);
|
|
1798
|
-
const openImpliesClose = new Map([
|
|
1799
|
-
["tr", new Set([
|
|
1795
|
+
const tableSectionTags = /* @__PURE__ */ new Set(["thead", "tbody"]);
|
|
1796
|
+
const ddtTags = /* @__PURE__ */ new Set(["dd", "dt"]);
|
|
1797
|
+
const rtpTags = /* @__PURE__ */ new Set(["rt", "rp"]);
|
|
1798
|
+
const openImpliesClose = /* @__PURE__ */ new Map([
|
|
1799
|
+
["tr", /* @__PURE__ */ new Set([
|
|
1800
1800
|
"tr",
|
|
1801
1801
|
"th",
|
|
1802
1802
|
"td"
|
|
1803
1803
|
])],
|
|
1804
|
-
["th", new Set(["th"])],
|
|
1805
|
-
["td", new Set([
|
|
1804
|
+
["th", /* @__PURE__ */ new Set(["th"])],
|
|
1805
|
+
["td", /* @__PURE__ */ new Set([
|
|
1806
1806
|
"thead",
|
|
1807
1807
|
"th",
|
|
1808
1808
|
"td"
|
|
1809
1809
|
])],
|
|
1810
|
-
["body", new Set([
|
|
1810
|
+
["body", /* @__PURE__ */ new Set([
|
|
1811
1811
|
"head",
|
|
1812
1812
|
"link",
|
|
1813
1813
|
"script"
|
|
1814
1814
|
])],
|
|
1815
|
-
["a", new Set(["a"])],
|
|
1816
|
-
["li", new Set(["li"])],
|
|
1815
|
+
["a", /* @__PURE__ */ new Set(["a"])],
|
|
1816
|
+
["li", /* @__PURE__ */ new Set(["li"])],
|
|
1817
1817
|
["p", pTag],
|
|
1818
1818
|
["h1", headingTags],
|
|
1819
1819
|
["h2", headingTags],
|
|
@@ -1827,8 +1827,8 @@ const openImpliesClose = new Map([
|
|
|
1827
1827
|
["button", formTags],
|
|
1828
1828
|
["datalist", formTags],
|
|
1829
1829
|
["textarea", formTags],
|
|
1830
|
-
["option", new Set(["option"])],
|
|
1831
|
-
["optgroup", new Set(["optgroup", "option"])],
|
|
1830
|
+
["option", /* @__PURE__ */ new Set(["option"])],
|
|
1831
|
+
["optgroup", /* @__PURE__ */ new Set(["optgroup", "option"])],
|
|
1832
1832
|
["dd", ddtTags],
|
|
1833
1833
|
["dt", ddtTags],
|
|
1834
1834
|
["address", pTag],
|
|
@@ -1858,7 +1858,7 @@ const openImpliesClose = new Map([
|
|
|
1858
1858
|
["tfoot", tableSectionTags]
|
|
1859
1859
|
]);
|
|
1860
1860
|
const DOCUMENT_TYPE = "doctype";
|
|
1861
|
-
const voidElements = new Set([
|
|
1861
|
+
const voidElements = /* @__PURE__ */ new Set([
|
|
1862
1862
|
"area",
|
|
1863
1863
|
"base",
|
|
1864
1864
|
"basefont",
|
|
@@ -1879,14 +1879,14 @@ const voidElements = new Set([
|
|
|
1879
1879
|
"track",
|
|
1880
1880
|
"wbr"
|
|
1881
1881
|
]);
|
|
1882
|
-
const foreignContextElements = new Set(["math", "svg"]);
|
|
1882
|
+
const foreignContextElements = /* @__PURE__ */ new Set(["math", "svg"]);
|
|
1883
1883
|
/**
|
|
1884
1884
|
* Elements that can be used to integrate HTML content within foreign namespaces (e.g., SVG or MathML).
|
|
1885
1885
|
*
|
|
1886
1886
|
* Entries must use the SVG-adjusted casing (e.g. "foreignObject" not
|
|
1887
1887
|
* "foreignobject") since they are compared against adjusted tag names.
|
|
1888
1888
|
*/
|
|
1889
|
-
const htmlIntegrationElements = new Set([
|
|
1889
|
+
const htmlIntegrationElements = /* @__PURE__ */ new Set([
|
|
1890
1890
|
"mi",
|
|
1891
1891
|
"mo",
|
|
1892
1892
|
"mn",
|
|
@@ -1897,7 +1897,7 @@ const htmlIntegrationElements = new Set([
|
|
|
1897
1897
|
"desc",
|
|
1898
1898
|
"title"
|
|
1899
1899
|
]);
|
|
1900
|
-
const svgTagNameAdjustments = new Map([
|
|
1900
|
+
const svgTagNameAdjustments = /* @__PURE__ */ new Map([
|
|
1901
1901
|
["altglyph", "altGlyph"],
|
|
1902
1902
|
["altglyphdef", "altGlyphDef"],
|
|
1903
1903
|
["altglyphitem", "altGlyphItem"],
|
|
@@ -2865,7 +2865,7 @@ const STRUCTURAL_ATTRS = [
|
|
|
2865
2865
|
"wx:for-index",
|
|
2866
2866
|
"wx:key"
|
|
2867
2867
|
];
|
|
2868
|
-
const WX_ELSE_ATTRS = new Set(["wx:elif", "wx:else"]);
|
|
2868
|
+
const WX_ELSE_ATTRS = /* @__PURE__ */ new Set(["wx:elif", "wx:else"]);
|
|
2869
2869
|
const CLASS_SPLIT_RE = /\s+/;
|
|
2870
2870
|
const JS_FILE_RE = /\.js$/;
|
|
2871
2871
|
function isMustacheOnly(value) {
|
|
@@ -5262,7 +5262,7 @@ const SAVED_FILE_PREFIXES = ["headless://saved/", "headless://wxfile/saved/"];
|
|
|
5262
5262
|
const textEncoder = new TextEncoder();
|
|
5263
5263
|
const IMAGE_EXTENSION_RE = /\.([^.?#/]+)(?:[?#].*)?$/;
|
|
5264
5264
|
const LEADING_DOT_RE = /^\.+/;
|
|
5265
|
-
const IMAGE_FILE_EXTENSIONS = new Set([
|
|
5265
|
+
const IMAGE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
5266
5266
|
"bmp",
|
|
5267
5267
|
"gif",
|
|
5268
5268
|
"heic",
|
|
@@ -5271,7 +5271,7 @@ const IMAGE_FILE_EXTENSIONS = new Set([
|
|
|
5271
5271
|
"png",
|
|
5272
5272
|
"webp"
|
|
5273
5273
|
]);
|
|
5274
|
-
const VIDEO_FILE_EXTENSIONS = new Set([
|
|
5274
|
+
const VIDEO_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
5275
5275
|
"avi",
|
|
5276
5276
|
"m4v",
|
|
5277
5277
|
"mov",
|
|
@@ -7547,7 +7547,7 @@ var HeadlessSession = class {
|
|
|
7547
7547
|
};
|
|
7548
7548
|
}
|
|
7549
7549
|
unloadAllPages() {
|
|
7550
|
-
const pagesToUnload = new Set([...this.pages, ...this.tabPages.values()]);
|
|
7550
|
+
const pagesToUnload = /* @__PURE__ */ new Set([...this.pages, ...this.tabPages.values()]);
|
|
7551
7551
|
for (const page of [...pagesToUnload].reverse()) this.unloadPage(page);
|
|
7552
7552
|
this.pages.length = 0;
|
|
7553
7553
|
this.tabPages.clear();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weapp-vite/miniprogram-automator",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.5",
|
|
5
5
|
"description": "完全兼容微信 miniprogram-automator 的现代化替代实现",
|
|
6
6
|
"author": "ice breaker <1324318532@qq.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/ws": "^8.18.1",
|
|
54
|
-
"sharp": "^0.35.
|
|
54
|
+
"sharp": "^0.35.2"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"dev": "tsdown -w --sourcemap",
|