@react-native/dev-middleware 0.73.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 ADDED
@@ -0,0 +1,11 @@
1
+ # @react-native/dev-middleware
2
+
3
+ ![https://img.shields.io/npm/v/@react-native/dev-middleware?color=brightgreen&label=npm%20package](https://www.npmjs.com/package/@react-native/dev-middleware)
4
+
5
+ Dev server middleware supporting core React Native development features. This package is preconfigured in all React Native projects.
6
+
7
+ ## Endpoints
8
+
9
+ ### `/open-debugger`
10
+
11
+ Open the JavaScript debugger for a given CDP target (direct Hermes debugging).
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true,
5
+ });
6
+ exports.default = createDevMiddleware;
7
+ var _connect = _interopRequireDefault(require("connect"));
8
+ var _openDebuggerMiddleware = _interopRequireDefault(
9
+ require("./middleware/openDebuggerMiddleware")
10
+ );
11
+ function _interopRequireDefault(obj) {
12
+ return obj && obj.__esModule ? obj : { default: obj };
13
+ }
14
+ /**
15
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
16
+ *
17
+ * This source code is licensed under the MIT license found in the
18
+ * LICENSE file in the root directory of this source tree.
19
+ *
20
+ *
21
+ * @format
22
+ * @oncall react_native
23
+ */
24
+
25
+ function createDevMiddleware({ logger } = {}) {
26
+ const middleware = (0, _connect.default)().use(
27
+ "/open-debugger",
28
+ (0, _openDebuggerMiddleware.default)({
29
+ logger,
30
+ })
31
+ );
32
+ return {
33
+ middleware,
34
+ };
35
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ import type {NextHandleFunction} from 'connect';
13
+ import type {Logger} from './types/Logger';
14
+
15
+ import connect from 'connect';
16
+ import openDebuggerMiddleware from './middleware/openDebuggerMiddleware';
17
+
18
+ type Options = $ReadOnly<{
19
+ logger?: Logger,
20
+ }>;
21
+
22
+ export default function createDevMiddleware({logger}: Options = {}): {
23
+ middleware: NextHandleFunction,
24
+ } {
25
+ const middleware = connect().use(
26
+ '/open-debugger',
27
+ openDebuggerMiddleware({logger}),
28
+ );
29
+
30
+ return {middleware};
31
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true,
5
+ });
6
+ Object.defineProperty(exports, "createDevMiddleware", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _createDevMiddleware.default;
10
+ },
11
+ });
12
+ var _createDevMiddleware = _interopRequireDefault(
13
+ require("./createDevMiddleware")
14
+ );
15
+ function _interopRequireDefault(obj) {
16
+ return obj && obj.__esModule ? obj : { default: obj };
17
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ export {default as createDevMiddleware} from './createDevMiddleware';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+
3
+ module.exports = require("./index.flow");
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ /*::
13
+ export type * from './index.flow';
14
+ */
15
+
16
+ if (!process.env.BUILD_EXCLUDE_BABEL_REGISTER) {
17
+ require('../../../scripts/build/babel-register').registerForMonorepo();
18
+ }
19
+
20
+ module.exports = require('./index.flow');
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true,
5
+ });
6
+ exports.default = openDebuggerMiddleware;
7
+ var _url = _interopRequireDefault(require("url"));
8
+ var _getDevServerUrl = _interopRequireDefault(
9
+ require("../utils/getDevServerUrl")
10
+ );
11
+ var _launchChromeDevTools = _interopRequireDefault(
12
+ require("../utils/launchChromeDevTools")
13
+ );
14
+ var _queryInspectorTargets = _interopRequireDefault(
15
+ require("../utils/queryInspectorTargets")
16
+ );
17
+ function _interopRequireDefault(obj) {
18
+ return obj && obj.__esModule ? obj : { default: obj };
19
+ }
20
+ /**
21
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
22
+ *
23
+ * This source code is licensed under the MIT license found in the
24
+ * LICENSE file in the root directory of this source tree.
25
+ *
26
+ *
27
+ * @format
28
+ * @oncall react_native
29
+ */
30
+
31
+ const debuggerInstances = new Map();
32
+ /**
33
+ * Open the JavaScript debugger for a given CDP target (direct Hermes debugging).
34
+ *
35
+ * Currently supports Hermes targets, opening debugger websocket URL in Chrome
36
+ * DevTools.
37
+ *
38
+ * @see https://chromedevtools.github.io/devtools-protocol/
39
+ */
40
+ function openDebuggerMiddleware({ logger }) {
41
+ return async (req, res, next) => {
42
+ if (req.method === "POST") {
43
+ const { query } = _url.default.parse(req.url, true);
44
+ const { appId } = query;
45
+ if (typeof appId !== "string") {
46
+ res.writeHead(400);
47
+ res.end();
48
+ return;
49
+ }
50
+ const targets = await (0, _queryInspectorTargets.default)(
51
+ (0, _getDevServerUrl.default)(req)
52
+ );
53
+ const target = targets.find((_target) => _target.description === appId);
54
+ if (!target) {
55
+ res.writeHead(404);
56
+ res.end("Unable to find Chrome DevTools inspector target");
57
+ logger?.warn(
58
+ "No compatible apps connected. JavaScript debugging can only be used with the Hermes engine."
59
+ );
60
+ return;
61
+ }
62
+ try {
63
+ logger?.info("Launching JS debugger...");
64
+ debuggerInstances.get(appId)?.kill();
65
+ debuggerInstances.set(
66
+ appId,
67
+ await (0, _launchChromeDevTools.default)(target.webSocketDebuggerUrl)
68
+ );
69
+ res.end();
70
+ return;
71
+ } catch (e) {
72
+ logger?.error(
73
+ "Error launching JS debugger: " + e.message ?? "Unknown error"
74
+ );
75
+ res.writeHead(500);
76
+ res.end();
77
+ return;
78
+ }
79
+ }
80
+ next();
81
+ };
82
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ import type {LaunchedChrome} from 'chrome-launcher';
13
+ import type {NextHandleFunction} from 'connect';
14
+ import type {IncomingMessage, ServerResponse} from 'http';
15
+ import type {Logger} from '../types/Logger';
16
+
17
+ import url from 'url';
18
+ import getDevServerUrl from '../utils/getDevServerUrl';
19
+ import launchChromeDevTools from '../utils/launchChromeDevTools';
20
+ import queryInspectorTargets from '../utils/queryInspectorTargets';
21
+
22
+ const debuggerInstances = new Map<string, LaunchedChrome>();
23
+
24
+ type Options = $ReadOnly<{
25
+ logger?: Logger,
26
+ }>;
27
+
28
+ /**
29
+ * Open the JavaScript debugger for a given CDP target (direct Hermes debugging).
30
+ *
31
+ * Currently supports Hermes targets, opening debugger websocket URL in Chrome
32
+ * DevTools.
33
+ *
34
+ * @see https://chromedevtools.github.io/devtools-protocol/
35
+ */
36
+ export default function openDebuggerMiddleware({
37
+ logger,
38
+ }: Options): NextHandleFunction {
39
+ return async (
40
+ req: IncomingMessage,
41
+ res: ServerResponse,
42
+ next: (err?: Error) => void,
43
+ ) => {
44
+ if (req.method === 'POST') {
45
+ const {query} = url.parse(req.url, true);
46
+ const {appId} = query;
47
+
48
+ if (typeof appId !== 'string') {
49
+ res.writeHead(400);
50
+ res.end();
51
+ return;
52
+ }
53
+
54
+ const targets = await queryInspectorTargets(getDevServerUrl(req));
55
+ const target = targets.find(_target => _target.description === appId);
56
+
57
+ if (!target) {
58
+ res.writeHead(404);
59
+ res.end('Unable to find Chrome DevTools inspector target');
60
+ logger?.warn(
61
+ 'No compatible apps connected. JavaScript debugging can only be used with the Hermes engine.',
62
+ );
63
+ return;
64
+ }
65
+
66
+ try {
67
+ logger?.info('Launching JS debugger...');
68
+ debuggerInstances.get(appId)?.kill();
69
+ debuggerInstances.set(
70
+ appId,
71
+ await launchChromeDevTools(target.webSocketDebuggerUrl),
72
+ );
73
+ res.end();
74
+ return;
75
+ } catch (e) {
76
+ logger?.error(
77
+ 'Error launching JS debugger: ' + e.message ?? 'Unknown error',
78
+ );
79
+ res.writeHead(500);
80
+ res.end();
81
+ return;
82
+ }
83
+ }
84
+
85
+ next();
86
+ };
87
+ }
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ export type Logger = $ReadOnly<{
13
+ error: (...message: Array<string>) => void,
14
+ info: (...message: Array<string>) => void,
15
+ warn: (...message: Array<string>) => void,
16
+ ...
17
+ }>;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true,
5
+ });
6
+ exports.default = getDevServerUrl;
7
+ var _net = _interopRequireDefault(require("net"));
8
+ var _tls = require("tls");
9
+ function _interopRequireDefault(obj) {
10
+ return obj && obj.__esModule ? obj : { default: obj };
11
+ }
12
+ /**
13
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
14
+ *
15
+ * This source code is licensed under the MIT license found in the
16
+ * LICENSE file in the root directory of this source tree.
17
+ *
18
+ *
19
+ * @format
20
+ * @oncall react_native
21
+ */
22
+
23
+ /**
24
+ * Get the base URL to address the current development server.
25
+ */
26
+ function getDevServerUrl(req) {
27
+ const scheme =
28
+ req.socket instanceof _tls.TLSSocket && req.socket.encrypted === true
29
+ ? "https"
30
+ : "http";
31
+ const { localAddress, localPort } = req.socket;
32
+ const address =
33
+ localAddress && _net.default.isIPv6(localAddress)
34
+ ? `[${localAddress}]`
35
+ : localAddress;
36
+ return `${scheme}:${address}:${localPort}`;
37
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ import type {IncomingMessage} from 'http';
13
+
14
+ import net from 'net';
15
+ import {TLSSocket} from 'tls';
16
+
17
+ /**
18
+ * Get the base URL to address the current development server.
19
+ */
20
+ export default function getDevServerUrl(req: IncomingMessage): string {
21
+ const scheme =
22
+ req.socket instanceof TLSSocket && req.socket.encrypted === true
23
+ ? 'https'
24
+ : 'http';
25
+ const {localAddress, localPort} = req.socket;
26
+ const address =
27
+ localAddress && net.isIPv6(localAddress)
28
+ ? `[${localAddress}]`
29
+ : localAddress;
30
+
31
+ return `${scheme}:${address}:${localPort}`;
32
+ }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true,
5
+ });
6
+ exports.default = launchChromeDevTools;
7
+ var _launchDebuggerAppWindow = _interopRequireDefault(
8
+ require("./launchDebuggerAppWindow")
9
+ );
10
+ function _interopRequireDefault(obj) {
11
+ return obj && obj.__esModule ? obj : { default: obj };
12
+ }
13
+ /**
14
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
15
+ *
16
+ * This source code is licensed under the MIT license found in the
17
+ * LICENSE file in the root directory of this source tree.
18
+ *
19
+ *
20
+ * @format
21
+ * @oncall react_native
22
+ */
23
+
24
+ /**
25
+ * The Chrome DevTools frontend revision to use. This should be set to the
26
+ * latest version known to be compatible with Hermes.
27
+ *
28
+ * Revision should be the full identifier from:
29
+ * https://chromium.googlesource.com/chromium/src.git
30
+ */
31
+ const DEVTOOLS_FRONTEND_REV = "d9568d04d7dd79269c5a655d7ada69650c5a8336"; // Chrome 100.0.4896.75
32
+
33
+ /**
34
+ * Attempt to launch Chrome DevTools on the host machine for a given CDP target.
35
+ */
36
+ async function launchChromeDevTools(webSocketDebuggerUrl) {
37
+ const ws = webSocketDebuggerUrl.replace(/^ws:\/\//, "");
38
+ return (0, _launchDebuggerAppWindow.default)(
39
+ `${`https://chrome-devtools-frontend.appspot.com/serve_rev/@${DEVTOOLS_FRONTEND_REV}/devtools_app.html`}?panel=console&ws=${encodeURIComponent(
40
+ ws
41
+ )}`,
42
+ "open-debugger"
43
+ );
44
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ import type {LaunchedChrome} from 'chrome-launcher';
13
+
14
+ import launchDebuggerAppWindow from './launchDebuggerAppWindow';
15
+
16
+ /**
17
+ * The Chrome DevTools frontend revision to use. This should be set to the
18
+ * latest version known to be compatible with Hermes.
19
+ *
20
+ * Revision should be the full identifier from:
21
+ * https://chromium.googlesource.com/chromium/src.git
22
+ */
23
+ const DEVTOOLS_FRONTEND_REV = 'd9568d04d7dd79269c5a655d7ada69650c5a8336'; // Chrome 100.0.4896.75
24
+
25
+ /**
26
+ * Attempt to launch Chrome DevTools on the host machine for a given CDP target.
27
+ */
28
+ export default async function launchChromeDevTools(
29
+ webSocketDebuggerUrl: string,
30
+ ): Promise<LaunchedChrome> {
31
+ const urlBase = `https://chrome-devtools-frontend.appspot.com/serve_rev/@${DEVTOOLS_FRONTEND_REV}/devtools_app.html`;
32
+ const ws = webSocketDebuggerUrl.replace(/^ws:\/\//, '');
33
+
34
+ return launchDebuggerAppWindow(
35
+ `${urlBase}?panel=console&ws=${encodeURIComponent(ws)}`,
36
+ 'open-debugger',
37
+ );
38
+ }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true,
5
+ });
6
+ exports.default = launchDebuggerAppWindow;
7
+ var _fs = require("fs");
8
+ var _path = _interopRequireDefault(require("path"));
9
+ var _tempDir = _interopRequireDefault(require("temp-dir"));
10
+ function _interopRequireDefault(obj) {
11
+ return obj && obj.__esModule ? obj : { default: obj };
12
+ }
13
+ /**
14
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
15
+ *
16
+ * This source code is licensed under the MIT license found in the
17
+ * LICENSE file in the root directory of this source tree.
18
+ *
19
+ *
20
+ * @format
21
+ * @oncall react_native
22
+ */
23
+
24
+ const ChromeLauncher = require("chrome-launcher");
25
+
26
+ /**
27
+ * Attempt to open a debugger frontend URL as a Google Chrome app window.
28
+ */
29
+ async function launchDebuggerAppWindow(
30
+ url,
31
+ /**
32
+ * Used to construct the temp browser dir to preserve settings such as window
33
+ * position.
34
+ */
35
+ intent
36
+ ) {
37
+ const userDataDir = await createTempDir(`react-native-${intent}-${"chrome"}`);
38
+ try {
39
+ return ChromeLauncher.launch({
40
+ chromeFlags: [
41
+ `--app=${url}`,
42
+ `--user-data-dir=${userDataDir}`,
43
+ "--window-size=1200,600",
44
+ ],
45
+ });
46
+ } catch (e) {
47
+ throw new Error(
48
+ "Unable to find a browser on the host to open the debugger. Supported browsers: Google Chrome"
49
+ );
50
+ }
51
+ }
52
+ async function createTempDir(dirName) {
53
+ const tempDir = _path.default.join(_tempDir.default, dirName);
54
+ await _fs.promises.mkdir(tempDir, {
55
+ recursive: true,
56
+ });
57
+ return tempDir;
58
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ import type {LaunchedChrome} from 'chrome-launcher';
13
+ import {promises as fs} from 'fs';
14
+ import path from 'path';
15
+ import osTempDir from 'temp-dir';
16
+
17
+ const ChromeLauncher = require('chrome-launcher');
18
+
19
+ /**
20
+ * Attempt to open a debugger frontend URL as a Google Chrome app window.
21
+ */
22
+ export default async function launchDebuggerAppWindow(
23
+ url: string,
24
+ /**
25
+ * Used to construct the temp browser dir to preserve settings such as window
26
+ * position.
27
+ */
28
+ intent: 'open-debugger',
29
+ ): Promise<LaunchedChrome> {
30
+ const browserType = 'chrome';
31
+ const userDataDir = await createTempDir(
32
+ `react-native-${intent}-${browserType}`,
33
+ );
34
+
35
+ try {
36
+ return ChromeLauncher.launch({
37
+ chromeFlags: [
38
+ `--app=${url}`,
39
+ `--user-data-dir=${userDataDir}`,
40
+ '--window-size=1200,600',
41
+ ],
42
+ });
43
+ } catch (e) {
44
+ throw new Error(
45
+ 'Unable to find a browser on the host to open the debugger. Supported browsers: Google Chrome',
46
+ );
47
+ }
48
+ }
49
+
50
+ async function createTempDir(dirName: string): Promise<string> {
51
+ const tempDir = path.join(osTempDir, dirName);
52
+
53
+ await fs.mkdir(tempDir, {recursive: true});
54
+
55
+ return tempDir;
56
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true,
5
+ });
6
+ exports.default = queryInspectorTargets;
7
+ var _nodeFetch = _interopRequireDefault(require("node-fetch"));
8
+ function _interopRequireDefault(obj) {
9
+ return obj && obj.__esModule ? obj : { default: obj };
10
+ }
11
+ /**
12
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
13
+ *
14
+ * This source code is licensed under the MIT license found in the
15
+ * LICENSE file in the root directory of this source tree.
16
+ *
17
+ *
18
+ * @format
19
+ * @oncall react_native
20
+ */
21
+
22
+ /**
23
+ * Get the list of available debug targets from the React Native dev server.
24
+ *
25
+ * @see https://chromedevtools.github.io/devtools-protocol/
26
+ */
27
+ async function queryInspectorTargets(devServerUrl) {
28
+ const res = await (0, _nodeFetch.default)(`${devServerUrl}/json/list`);
29
+ const apps = await res.json();
30
+
31
+ // Only use targets with better reloading support
32
+ return apps.filter(
33
+ (app) => app.title === "React Native Experimental (Improved Chrome Reloads)"
34
+ );
35
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ * @oncall react_native
10
+ */
11
+
12
+ import fetch from 'node-fetch';
13
+
14
+ type ReactNativeCDPTarget = {
15
+ id: string,
16
+ description: string,
17
+ title: string,
18
+ type: string,
19
+ devtoolsFrontendUrl: string,
20
+ webSocketDebuggerUrl: string,
21
+ vm: string,
22
+ deviceName?: string,
23
+ };
24
+
25
+ /**
26
+ * Get the list of available debug targets from the React Native dev server.
27
+ *
28
+ * @see https://chromedevtools.github.io/devtools-protocol/
29
+ */
30
+ export default async function queryInspectorTargets(
31
+ devServerUrl: string,
32
+ ): Promise<ReactNativeCDPTarget[]> {
33
+ const res = await fetch(`${devServerUrl}/json/list`);
34
+ const apps = (await res.json(): Array<ReactNativeCDPTarget>);
35
+
36
+ // Only use targets with better reloading support
37
+ return apps.filter(
38
+ app => app.title === 'React Native Experimental (Improved Chrome Reloads)',
39
+ );
40
+ }
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@react-native/dev-middleware",
3
+ "version": "0.73.0",
4
+ "description": "Dev server middleware for React Native",
5
+ "keywords": ["react-native", "tools"],
6
+ "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/dev-middleware#readme",
7
+ "bugs": "https://github.com/facebook/react-native/issues",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/facebook/react-native.git",
11
+ "directory": "packages/dev-middleware"
12
+ },
13
+ "license": "MIT",
14
+ "exports": { ".": "./dist/index.js", "./package.json": "./package.json" },
15
+ "files": ["dist"],
16
+ "dependencies": {
17
+ "chrome-launcher": "^0.15.2",
18
+ "connect": "^3.6.5",
19
+ "node-fetch": "^2.2.0",
20
+ "temp-dir": "^2.0.0"
21
+ },
22
+ "engines": { "node": ">=18" }
23
+ }