@xbrowser/cli 1.13.0 → 1.14.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/dist/{browser-AQ2AT2YZ.js → browser-5A6AL62M.js} +2 -2
- package/dist/{browser-OMGJMSBB.js → browser-DI6UQN6Q.js} +1 -1
- package/dist/{browser-T7OVLAEC.js → browser-KJWBHGHX.js} +2 -2
- package/dist/{cdp-driver-VS7Z7W7Y.js → cdp-driver-4SFS6GNY.js} +1 -1
- package/dist/{cdp-driver-HYCLE4YP.js → cdp-driver-AHKUT57K.js} +1 -1
- package/dist/{cdp-driver-ALDNOZYD.js → cdp-driver-QXTXJZH7.js} +18 -5
- package/dist/{chunk-CW7L53JE.js → chunk-B753M33E.js} +1 -1
- package/dist/{chunk-BY5TT6WZ.js → chunk-BTFKJD7Z.js} +18 -5
- package/dist/{chunk-R2POF2GP.js → chunk-PYQGDBAF.js} +18 -5
- package/dist/{chunk-T2CNKWPV.js → chunk-UPAWITVM.js} +18 -5
- package/dist/{chunk-HD4FX2N5.js → chunk-ZD4OSYOX.js} +1 -1
- package/dist/cli.js +4 -4
- package/dist/daemon-main.js +4 -4
- package/dist/index.js +5 -5
- package/dist/{session-replayer-UVH5FGY2.js → session-replayer-I3PJFO3H.js} +1 -1
- package/package.json +1 -1
|
@@ -20,8 +20,8 @@ import {
|
|
|
20
20
|
saveSessionDiskMeta,
|
|
21
21
|
setActivePage,
|
|
22
22
|
touchSession
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import "./chunk-
|
|
23
|
+
} from "./chunk-ZD4OSYOX.js";
|
|
24
|
+
import "./chunk-UPAWITVM.js";
|
|
25
25
|
import "./chunk-3FWLW7FS.js";
|
|
26
26
|
import "./chunk-TNEN6VQ2.js";
|
|
27
27
|
import "./chunk-GDKLH7ZY.js";
|
|
@@ -20,8 +20,8 @@ import {
|
|
|
20
20
|
saveSessionDiskMeta,
|
|
21
21
|
setActivePage,
|
|
22
22
|
touchSession
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import "./chunk-
|
|
23
|
+
} from "./chunk-B753M33E.js";
|
|
24
|
+
import "./chunk-PYQGDBAF.js";
|
|
25
25
|
import "./chunk-TNEN6VQ2.js";
|
|
26
26
|
import "./chunk-GDKLH7ZY.js";
|
|
27
27
|
import "./chunk-A6LPGFAL.js";
|
|
@@ -122,10 +122,10 @@ function buildStealthInitScript() {
|
|
|
122
122
|
" var op=arguments[2];",
|
|
123
123
|
' if(typeof f!=="function")return o.call(this,t,f,op);',
|
|
124
124
|
" var w=function(e){",
|
|
125
|
-
" if(!e
|
|
125
|
+
" if(!e)return f.call(this,e);",
|
|
126
126
|
" return f.call(this,new Proxy(e,{get:function(k,p){",
|
|
127
127
|
' if(p==="sourceCapabilities")return fc;',
|
|
128
|
-
' if(p==="isTrusted")return k
|
|
128
|
+
' if(p==="isTrusted")return Reflect.get(k,"isTrusted");',
|
|
129
129
|
' if((p==="clientX"||p==="clientY")&&k.type==="click"&&Number.isInteger(k[p])&&k.isTrusted===true){',
|
|
130
130
|
" var _f=((k.timeStamp||Date.now())%89)/89*0.7+0.15;",
|
|
131
131
|
" return k[p]+_f;",
|
|
@@ -315,7 +315,7 @@ function buildStealthInitScript() {
|
|
|
315
315
|
" };",
|
|
316
316
|
// 4. onclick prototype hijack (dual-stream consistency)
|
|
317
317
|
" var _ba=function(k,p){",
|
|
318
|
-
' if(p==="isTrusted")return k
|
|
318
|
+
' if(p==="isTrusted")return Reflect.get(k,"isTrusted");',
|
|
319
319
|
' if((p==="clientX"||p==="clientY")&&k.type==="click"&&Number.isInteger(k[p])&&k.isTrusted===true){',
|
|
320
320
|
" var _f=((k.timeStamp||Date.now())%89)/89*0.7+0.15;return k[p]+_f;",
|
|
321
321
|
" }",
|
|
@@ -535,9 +535,22 @@ var XBKeyboardImpl = class {
|
|
|
535
535
|
await this.dispatchKeyEvent(params);
|
|
536
536
|
}
|
|
537
537
|
async type(text, opts = {}) {
|
|
538
|
-
const
|
|
538
|
+
const stealth = opts.stealth ?? process.env.XBROWSER_STEALTH !== "off";
|
|
539
|
+
const fixedDelay = opts.delay ?? 0;
|
|
539
540
|
for (const char of text) {
|
|
540
|
-
if (
|
|
541
|
+
if (fixedDelay > 0) {
|
|
542
|
+
await sleep2(fixedDelay);
|
|
543
|
+
} else if (stealth) {
|
|
544
|
+
const roll = Math.random();
|
|
545
|
+
const cfg = DEFAULT_STEALTH_CONFIG.typingRhythm;
|
|
546
|
+
if (roll < cfg.pauseProb) {
|
|
547
|
+
await sleep2(rand(cfg.pauseRange[0], cfg.pauseRange[1]));
|
|
548
|
+
} else if (roll < cfg.pauseProb + cfg.fastProb) {
|
|
549
|
+
await sleep2(rand(cfg.fastRange[0], cfg.fastRange[1]));
|
|
550
|
+
} else {
|
|
551
|
+
await sleep2(rand(cfg.normalRange[0], cfg.normalRange[1]));
|
|
552
|
+
}
|
|
553
|
+
}
|
|
541
554
|
const mapping = resolveKeyMapping(char);
|
|
542
555
|
const downParams = {
|
|
543
556
|
type: "rawKeyDown",
|
|
@@ -127,10 +127,10 @@ function buildStealthInitScript() {
|
|
|
127
127
|
" var op=arguments[2];",
|
|
128
128
|
' if(typeof f!=="function")return o.call(this,t,f,op);',
|
|
129
129
|
" var w=function(e){",
|
|
130
|
-
" if(!e
|
|
130
|
+
" if(!e)return f.call(this,e);",
|
|
131
131
|
" return f.call(this,new Proxy(e,{get:function(k,p){",
|
|
132
132
|
' if(p==="sourceCapabilities")return fc;',
|
|
133
|
-
' if(p==="isTrusted")return k
|
|
133
|
+
' if(p==="isTrusted")return Reflect.get(k,"isTrusted");',
|
|
134
134
|
' if((p==="clientX"||p==="clientY")&&k.type==="click"&&Number.isInteger(k[p])&&k.isTrusted===true){',
|
|
135
135
|
" var _f=((k.timeStamp||Date.now())%89)/89*0.7+0.15;",
|
|
136
136
|
" return k[p]+_f;",
|
|
@@ -320,7 +320,7 @@ function buildStealthInitScript() {
|
|
|
320
320
|
" };",
|
|
321
321
|
// 4. onclick prototype hijack (dual-stream consistency)
|
|
322
322
|
" var _ba=function(k,p){",
|
|
323
|
-
' if(p==="isTrusted")return k
|
|
323
|
+
' if(p==="isTrusted")return Reflect.get(k,"isTrusted");',
|
|
324
324
|
' if((p==="clientX"||p==="clientY")&&k.type==="click"&&Number.isInteger(k[p])&&k.isTrusted===true){',
|
|
325
325
|
" var _f=((k.timeStamp||Date.now())%89)/89*0.7+0.15;return k[p]+_f;",
|
|
326
326
|
" }",
|
|
@@ -540,9 +540,22 @@ var XBKeyboardImpl = class {
|
|
|
540
540
|
await this.dispatchKeyEvent(params);
|
|
541
541
|
}
|
|
542
542
|
async type(text, opts = {}) {
|
|
543
|
-
const
|
|
543
|
+
const stealth = opts.stealth ?? process.env.XBROWSER_STEALTH !== "off";
|
|
544
|
+
const fixedDelay = opts.delay ?? 0;
|
|
544
545
|
for (const char of text) {
|
|
545
|
-
if (
|
|
546
|
+
if (fixedDelay > 0) {
|
|
547
|
+
await sleep2(fixedDelay);
|
|
548
|
+
} else if (stealth) {
|
|
549
|
+
const roll = Math.random();
|
|
550
|
+
const cfg = DEFAULT_STEALTH_CONFIG.typingRhythm;
|
|
551
|
+
if (roll < cfg.pauseProb) {
|
|
552
|
+
await sleep2(rand(cfg.pauseRange[0], cfg.pauseRange[1]));
|
|
553
|
+
} else if (roll < cfg.pauseProb + cfg.fastProb) {
|
|
554
|
+
await sleep2(rand(cfg.fastRange[0], cfg.fastRange[1]));
|
|
555
|
+
} else {
|
|
556
|
+
await sleep2(rand(cfg.normalRange[0], cfg.normalRange[1]));
|
|
557
|
+
}
|
|
558
|
+
}
|
|
546
559
|
const mapping = resolveKeyMapping(char);
|
|
547
560
|
const downParams = {
|
|
548
561
|
type: "rawKeyDown",
|
|
@@ -124,10 +124,10 @@ function buildStealthInitScript() {
|
|
|
124
124
|
" var op=arguments[2];",
|
|
125
125
|
' if(typeof f!=="function")return o.call(this,t,f,op);',
|
|
126
126
|
" var w=function(e){",
|
|
127
|
-
" if(!e
|
|
127
|
+
" if(!e)return f.call(this,e);",
|
|
128
128
|
" return f.call(this,new Proxy(e,{get:function(k,p){",
|
|
129
129
|
' if(p==="sourceCapabilities")return fc;',
|
|
130
|
-
' if(p==="isTrusted")return k
|
|
130
|
+
' if(p==="isTrusted")return Reflect.get(k,"isTrusted");',
|
|
131
131
|
' if((p==="clientX"||p==="clientY")&&k.type==="click"&&Number.isInteger(k[p])&&k.isTrusted===true){',
|
|
132
132
|
" var _f=((k.timeStamp||Date.now())%89)/89*0.7+0.15;",
|
|
133
133
|
" return k[p]+_f;",
|
|
@@ -317,7 +317,7 @@ function buildStealthInitScript() {
|
|
|
317
317
|
" };",
|
|
318
318
|
// 4. onclick prototype hijack (dual-stream consistency)
|
|
319
319
|
" var _ba=function(k,p){",
|
|
320
|
-
' if(p==="isTrusted")return k
|
|
320
|
+
' if(p==="isTrusted")return Reflect.get(k,"isTrusted");',
|
|
321
321
|
' if((p==="clientX"||p==="clientY")&&k.type==="click"&&Number.isInteger(k[p])&&k.isTrusted===true){',
|
|
322
322
|
" var _f=((k.timeStamp||Date.now())%89)/89*0.7+0.15;return k[p]+_f;",
|
|
323
323
|
" }",
|
|
@@ -537,9 +537,22 @@ var XBKeyboardImpl = class {
|
|
|
537
537
|
await this.dispatchKeyEvent(params);
|
|
538
538
|
}
|
|
539
539
|
async type(text, opts = {}) {
|
|
540
|
-
const
|
|
540
|
+
const stealth = opts.stealth ?? process.env.XBROWSER_STEALTH !== "off";
|
|
541
|
+
const fixedDelay = opts.delay ?? 0;
|
|
541
542
|
for (const char of text) {
|
|
542
|
-
if (
|
|
543
|
+
if (fixedDelay > 0) {
|
|
544
|
+
await sleep2(fixedDelay);
|
|
545
|
+
} else if (stealth) {
|
|
546
|
+
const roll = Math.random();
|
|
547
|
+
const cfg = DEFAULT_STEALTH_CONFIG.typingRhythm;
|
|
548
|
+
if (roll < cfg.pauseProb) {
|
|
549
|
+
await sleep2(rand(cfg.pauseRange[0], cfg.pauseRange[1]));
|
|
550
|
+
} else if (roll < cfg.pauseProb + cfg.fastProb) {
|
|
551
|
+
await sleep2(rand(cfg.fastRange[0], cfg.fastRange[1]));
|
|
552
|
+
} else {
|
|
553
|
+
await sleep2(rand(cfg.normalRange[0], cfg.normalRange[1]));
|
|
554
|
+
}
|
|
555
|
+
}
|
|
543
556
|
const mapping = resolveKeyMapping(char);
|
|
544
557
|
const downParams = {
|
|
545
558
|
type: "rawKeyDown",
|
|
@@ -125,10 +125,10 @@ function buildStealthInitScript() {
|
|
|
125
125
|
" var op=arguments[2];",
|
|
126
126
|
' if(typeof f!=="function")return o.call(this,t,f,op);',
|
|
127
127
|
" var w=function(e){",
|
|
128
|
-
" if(!e
|
|
128
|
+
" if(!e)return f.call(this,e);",
|
|
129
129
|
" return f.call(this,new Proxy(e,{get:function(k,p){",
|
|
130
130
|
' if(p==="sourceCapabilities")return fc;',
|
|
131
|
-
' if(p==="isTrusted")return k
|
|
131
|
+
' if(p==="isTrusted")return Reflect.get(k,"isTrusted");',
|
|
132
132
|
' if((p==="clientX"||p==="clientY")&&k.type==="click"&&Number.isInteger(k[p])&&k.isTrusted===true){',
|
|
133
133
|
" var _f=((k.timeStamp||Date.now())%89)/89*0.7+0.15;",
|
|
134
134
|
" return k[p]+_f;",
|
|
@@ -318,7 +318,7 @@ function buildStealthInitScript() {
|
|
|
318
318
|
" };",
|
|
319
319
|
// 4. onclick prototype hijack (dual-stream consistency)
|
|
320
320
|
" var _ba=function(k,p){",
|
|
321
|
-
' if(p==="isTrusted")return k
|
|
321
|
+
' if(p==="isTrusted")return Reflect.get(k,"isTrusted");',
|
|
322
322
|
' if((p==="clientX"||p==="clientY")&&k.type==="click"&&Number.isInteger(k[p])&&k.isTrusted===true){',
|
|
323
323
|
" var _f=((k.timeStamp||Date.now())%89)/89*0.7+0.15;return k[p]+_f;",
|
|
324
324
|
" }",
|
|
@@ -538,9 +538,22 @@ var XBKeyboardImpl = class {
|
|
|
538
538
|
await this.dispatchKeyEvent(params);
|
|
539
539
|
}
|
|
540
540
|
async type(text, opts = {}) {
|
|
541
|
-
const
|
|
541
|
+
const stealth = opts.stealth ?? process.env.XBROWSER_STEALTH !== "off";
|
|
542
|
+
const fixedDelay = opts.delay ?? 0;
|
|
542
543
|
for (const char of text) {
|
|
543
|
-
if (
|
|
544
|
+
if (fixedDelay > 0) {
|
|
545
|
+
await sleep2(fixedDelay);
|
|
546
|
+
} else if (stealth) {
|
|
547
|
+
const roll = Math.random();
|
|
548
|
+
const cfg = DEFAULT_STEALTH_CONFIG.typingRhythm;
|
|
549
|
+
if (roll < cfg.pauseProb) {
|
|
550
|
+
await sleep2(rand(cfg.pauseRange[0], cfg.pauseRange[1]));
|
|
551
|
+
} else if (roll < cfg.pauseProb + cfg.fastProb) {
|
|
552
|
+
await sleep2(rand(cfg.fastRange[0], cfg.fastRange[1]));
|
|
553
|
+
} else {
|
|
554
|
+
await sleep2(rand(cfg.normalRange[0], cfg.normalRange[1]));
|
|
555
|
+
}
|
|
556
|
+
}
|
|
544
557
|
const mapping = resolveKeyMapping(char);
|
|
545
558
|
const downParams = {
|
|
546
559
|
type: "rawKeyDown",
|
package/dist/cli.js
CHANGED
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
resolveLaunchOpts,
|
|
60
60
|
saveSessionDiskMeta,
|
|
61
61
|
setActivePage
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-BTFKJD7Z.js";
|
|
63
63
|
import "./chunk-TNEN6VQ2.js";
|
|
64
64
|
import {
|
|
65
65
|
errMsg
|
|
@@ -7523,7 +7523,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7523
7523
|
}
|
|
7524
7524
|
let targetPageOverride = null;
|
|
7525
7525
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
7526
|
-
const { findTargetPage } = await import("./browser-
|
|
7526
|
+
const { findTargetPage } = await import("./browser-DI6UQN6Q.js");
|
|
7527
7527
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
7528
7528
|
if (!targetPageOverride) {
|
|
7529
7529
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -13663,7 +13663,7 @@ Run "xbrowser ${command} ${subCommand} --help" to see available parameters.`
|
|
|
13663
13663
|
const targetPage = pages[cmdTabIndex];
|
|
13664
13664
|
await targetPage.bringToFront().catch(() => {
|
|
13665
13665
|
});
|
|
13666
|
-
const { setActivePage: setActivePage2 } = await import("./browser-
|
|
13666
|
+
const { setActivePage: setActivePage2 } = await import("./browser-DI6UQN6Q.js");
|
|
13667
13667
|
setActivePage2(session, targetPage);
|
|
13668
13668
|
}
|
|
13669
13669
|
}
|
|
@@ -13939,7 +13939,7 @@ async function main() {
|
|
|
13939
13939
|
const command = process.argv[2];
|
|
13940
13940
|
const isLongRunning = command === "preview" || command === "serve";
|
|
13941
13941
|
if (!isLongRunning) {
|
|
13942
|
-
const { ensureProcessCanExit } = await import("./browser-
|
|
13942
|
+
const { ensureProcessCanExit } = await import("./browser-DI6UQN6Q.js");
|
|
13943
13943
|
await ensureProcessCanExit().catch(() => {
|
|
13944
13944
|
});
|
|
13945
13945
|
process.exit(process.exitCode || exitCode);
|
package/dist/daemon-main.js
CHANGED
|
@@ -30,10 +30,10 @@ import {
|
|
|
30
30
|
resolveLaunchOpts,
|
|
31
31
|
saveSessionDiskMeta,
|
|
32
32
|
setActivePage
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-ZD4OSYOX.js";
|
|
34
34
|
import {
|
|
35
35
|
createRuleEngine
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-UPAWITVM.js";
|
|
37
37
|
import {
|
|
38
38
|
queryJS
|
|
39
39
|
} from "./chunk-3FWLW7FS.js";
|
|
@@ -7041,7 +7041,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7041
7041
|
}
|
|
7042
7042
|
let targetPageOverride = null;
|
|
7043
7043
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
7044
|
-
const { findTargetPage } = await import("./browser-
|
|
7044
|
+
const { findTargetPage } = await import("./browser-5A6AL62M.js");
|
|
7045
7045
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
7046
7046
|
if (!targetPageOverride) {
|
|
7047
7047
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -8857,7 +8857,7 @@ function createRPCHandler() {
|
|
|
8857
8857
|
if (isNewFormat) {
|
|
8858
8858
|
try {
|
|
8859
8859
|
const replayErrors = [];
|
|
8860
|
-
const { SessionReplayer } = await import("./session-replayer-
|
|
8860
|
+
const { SessionReplayer } = await import("./session-replayer-I3PJFO3H.js");
|
|
8861
8861
|
const replayer = new SessionReplayer({
|
|
8862
8862
|
page: session.page,
|
|
8863
8863
|
stepDelay: slowMo * 500,
|
package/dist/index.js
CHANGED
|
@@ -92,8 +92,8 @@ import {
|
|
|
92
92
|
resolveLaunchOpts,
|
|
93
93
|
saveSessionDiskMeta,
|
|
94
94
|
setActivePage
|
|
95
|
-
} from "./chunk-
|
|
96
|
-
import "./chunk-
|
|
95
|
+
} from "./chunk-B753M33E.js";
|
|
96
|
+
import "./chunk-PYQGDBAF.js";
|
|
97
97
|
import "./chunk-TNEN6VQ2.js";
|
|
98
98
|
import {
|
|
99
99
|
errMsg
|
|
@@ -7873,7 +7873,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7873
7873
|
}
|
|
7874
7874
|
let targetPageOverride = null;
|
|
7875
7875
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
7876
|
-
const { findTargetPage } = await import("./browser-
|
|
7876
|
+
const { findTargetPage } = await import("./browser-KJWBHGHX.js");
|
|
7877
7877
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
7878
7878
|
if (!targetPageOverride) {
|
|
7879
7879
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -14051,7 +14051,7 @@ Run "xbrowser ${command} ${subCommand} --help" to see available parameters.`
|
|
|
14051
14051
|
const targetPage = pages[cmdTabIndex];
|
|
14052
14052
|
await targetPage.bringToFront().catch(() => {
|
|
14053
14053
|
});
|
|
14054
|
-
const { setActivePage: setActivePage2 } = await import("./browser-
|
|
14054
|
+
const { setActivePage: setActivePage2 } = await import("./browser-KJWBHGHX.js");
|
|
14055
14055
|
setActivePage2(session, targetPage);
|
|
14056
14056
|
}
|
|
14057
14057
|
}
|
|
@@ -17224,7 +17224,7 @@ var DataCollector = class {
|
|
|
17224
17224
|
return results;
|
|
17225
17225
|
}
|
|
17226
17226
|
async createBrowserContext() {
|
|
17227
|
-
const { launch } = await import("./cdp-driver-
|
|
17227
|
+
const { launch } = await import("./cdp-driver-AHKUT57K.js");
|
|
17228
17228
|
const { browser } = await launch({
|
|
17229
17229
|
headless: true,
|
|
17230
17230
|
args: ["--no-sandbox", "--disable-setuid-sandbox"]
|
|
@@ -34,7 +34,7 @@ var SessionReplayer = class {
|
|
|
34
34
|
if (this.opts.page) {
|
|
35
35
|
this.page = this.opts.page;
|
|
36
36
|
} else if (this.opts.cdpUrl) {
|
|
37
|
-
const { launch } = await import("./cdp-driver-
|
|
37
|
+
const { launch } = await import("./cdp-driver-4SFS6GNY.js");
|
|
38
38
|
const { browser } = await launch({ cdpEndpoint: this.opts.cdpUrl });
|
|
39
39
|
let contexts = browser.contexts();
|
|
40
40
|
for (let i = 0; i < 10 && contexts.length === 0; i++) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xbrowser/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "Browser automation CLI for web scraping, headless browsing, SEO analysis, and AI agent workflows. A command-line alternative to Playwright, Puppeteer, and Selenium.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|