mirror of
https://github.com/bitwarden/browser.git
synced 2025-02-28 03:21:40 +01:00
Make native-messaging-test-runner use desktop_proxy (#11923)
* Make native-messaging-test-runner use desktop_proxy * Remove node-ipc * Fix build and implement proxy selection * Remove eslint disable --------- Co-authored-by: Matt Bishop <mbishop@bitwarden.com>
This commit is contained in:
parent
f66446fa69
commit
240f9f9348
@ -12,15 +12,13 @@
|
||||
"@bitwarden/common": "file:../../../libs/common",
|
||||
"@bitwarden/node": "file:../../../libs/node",
|
||||
"module-alias": "2.2.3",
|
||||
"node-ipc": "9.2.1",
|
||||
"ts-node": "10.9.2",
|
||||
"uuid": "11.0.5",
|
||||
"yargs": "17.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "22.10.7",
|
||||
"@types/node-ipc": "9.2.3",
|
||||
"typescript": "4.7.4"
|
||||
"typescript": "5.4.2"
|
||||
}
|
||||
},
|
||||
"../../../libs/common": {
|
||||
@ -31,10 +29,7 @@
|
||||
"../../../libs/node": {
|
||||
"name": "@bitwarden/node",
|
||||
"version": "0.0.0",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@bitwarden/common": "file:../common"
|
||||
}
|
||||
"license": "GPL-3.0"
|
||||
},
|
||||
"node_modules/@bitwarden/common": {
|
||||
"resolved": "../../../libs/common",
|
||||
@ -114,16 +109,6 @@
|
||||
"undici-types": "~6.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node-ipc": {
|
||||
"version": "9.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-ipc/-/node-ipc-9.2.3.tgz",
|
||||
"integrity": "sha512-/MvSiF71fYf3+zwqkh/zkVkZj1hl1Uobre9EMFy08mqfJNAmpR0vmPgOUdEIDVgifxHj6G1vYMPLSBLLxoDACQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
|
||||
@ -225,15 +210,6 @@
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/easy-stack": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz",
|
||||
"integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
@ -249,15 +225,6 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/event-pubsub": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz",
|
||||
"integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==",
|
||||
"license": "Unlicense",
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
@ -276,27 +243,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/js-message": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz",
|
||||
"integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/js-queue": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.2.tgz",
|
||||
"integrity": "sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"easy-stack": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
@ -309,20 +255,6 @@
|
||||
"integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-ipc": {
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.2.1.tgz",
|
||||
"integrity": "sha512-mJzaM6O3xHf9VT8BULvJSbdVbmHUKRNOH7zDDkCrA1/T+CVjq2WVIDfLt0azZRXpgArJtl3rtmEozrbXPZ9GaQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"event-pubsub": "4.3.0",
|
||||
"js-message": "1.0.7",
|
||||
"js-queue": "2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
@ -402,16 +334,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.7.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
||||
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
||||
"license": "Apache-2.0",
|
||||
"version": "5.4.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz",
|
||||
"integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
|
@ -17,15 +17,13 @@
|
||||
"@bitwarden/common": "file:../../../libs/common",
|
||||
"@bitwarden/node": "file:../../../libs/node",
|
||||
"module-alias": "2.2.3",
|
||||
"node-ipc": "9.2.1",
|
||||
"ts-node": "10.9.2",
|
||||
"uuid": "11.0.5",
|
||||
"yargs": "17.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "22.10.7",
|
||||
"@types/node-ipc": "9.2.3",
|
||||
"typescript": "4.7.4"
|
||||
"typescript": "5.4.2"
|
||||
},
|
||||
"_moduleAliases": {
|
||||
"@bitwarden/common": "dist/libs/common/src",
|
||||
|
@ -1,9 +1,7 @@
|
||||
/* eslint-disable no-console */
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { homedir } from "os";
|
||||
|
||||
import * as NodeIPC from "node-ipc";
|
||||
import { ChildProcess, spawn } from "child_process";
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { MessageCommon } from "../../src/models/native-messaging/message-common";
|
||||
@ -13,11 +11,6 @@ import { UnencryptedMessageResponse } from "../../src/models/native-messaging/un
|
||||
import Deferred from "./deferred";
|
||||
import { race } from "./race";
|
||||
|
||||
NodeIPC.config.id = "native-messaging-test-runner";
|
||||
NodeIPC.config.maxRetries = 0;
|
||||
NodeIPC.config.silent = true;
|
||||
|
||||
const DESKTOP_APP_PATH = `${homedir}/tmp/app.bitwarden`;
|
||||
const DEFAULT_MESSAGE_TIMEOUT = 10 * 1000; // 10 seconds
|
||||
|
||||
export type MessageHandler = (MessageCommon) => void;
|
||||
@ -42,6 +35,10 @@ export default class IPCService {
|
||||
// A set of deferred promises that are awaiting socket connection
|
||||
private awaitingConnection = new Set<Deferred<void>>();
|
||||
|
||||
// The IPC desktop_proxy process
|
||||
private process?: ChildProcess;
|
||||
private processOutputBuffer = Buffer.alloc(0);
|
||||
|
||||
constructor(
|
||||
private socketName: string,
|
||||
private messageHandler: MessageHandler,
|
||||
@ -72,47 +69,47 @@ export default class IPCService {
|
||||
private _connect() {
|
||||
this.connectionState = IPCConnectionState.Connecting;
|
||||
|
||||
NodeIPC.connectTo(this.socketName, DESKTOP_APP_PATH, () => {
|
||||
// Process incoming message
|
||||
this.getSocket().on("message", (message: any) => {
|
||||
this.processMessage(message);
|
||||
});
|
||||
const proxyPath = selectProxyPath();
|
||||
console.log(`[IPCService] connecting to proxy at ${proxyPath}`);
|
||||
|
||||
this.getSocket().on("error", (error: Error) => {
|
||||
// Only makes sense as long as config.maxRetries stays set to 0. Otherwise this will be
|
||||
// invoked multiple times each time a connection error happens
|
||||
console.log("[IPCService] errored");
|
||||
console.log(
|
||||
"\x1b[33m Please make sure the desktop app is running locally and 'Allow DuckDuckGo browser integration' setting is enabled \x1b[0m",
|
||||
);
|
||||
this.awaitingConnection.forEach((deferred) => {
|
||||
console.log(`rejecting: ${deferred}`);
|
||||
deferred.reject(error);
|
||||
});
|
||||
this.awaitingConnection.clear();
|
||||
});
|
||||
this.process = spawn(proxyPath, process.argv.slice(1), {
|
||||
cwd: process.cwd(),
|
||||
stdio: "pipe",
|
||||
shell: false,
|
||||
});
|
||||
|
||||
this.getSocket().on("connect", () => {
|
||||
console.log("[IPCService] connected");
|
||||
this.connectionState = IPCConnectionState.Connected;
|
||||
this.process.stdout.on("data", (data: Buffer) => {
|
||||
this.processIpcMessage(data);
|
||||
});
|
||||
|
||||
this.awaitingConnection.forEach((deferred) => {
|
||||
deferred.resolve(null);
|
||||
});
|
||||
this.awaitingConnection.clear();
|
||||
});
|
||||
this.process.stderr.on("data", (data: Buffer) => {
|
||||
console.error(`proxy log: ${data}`);
|
||||
});
|
||||
|
||||
this.getSocket().on("disconnect", () => {
|
||||
console.log("[IPCService] disconnected");
|
||||
this.connectionState = IPCConnectionState.Disconnected;
|
||||
this.process.on("error", (error) => {
|
||||
// Only makes sense as long as config.maxRetries stays set to 0. Otherwise this will be
|
||||
// invoked multiple times each time a connection error happens
|
||||
console.log("[IPCService] errored");
|
||||
console.log(
|
||||
"\x1b[33m Please make sure the desktop app is running locally and 'Allow DuckDuckGo browser integration' setting is enabled \x1b[0m",
|
||||
);
|
||||
this.awaitingConnection.forEach((deferred) => {
|
||||
console.log(`rejecting: ${deferred}`);
|
||||
deferred.reject(error);
|
||||
});
|
||||
this.awaitingConnection.clear();
|
||||
});
|
||||
|
||||
this.process.on("exit", () => {
|
||||
console.log("[IPCService] disconnected");
|
||||
this.connectionState = IPCConnectionState.Disconnected;
|
||||
});
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
console.log("[IPCService] disconnecting...");
|
||||
if (this.connectionState !== IPCConnectionState.Disconnected) {
|
||||
NodeIPC.disconnect(this.socketName);
|
||||
this.process?.kill();
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,7 +130,7 @@ export default class IPCService {
|
||||
|
||||
this.pendingMessages.set(message.messageId, deferred);
|
||||
|
||||
this.getSocket().emit("message", message);
|
||||
this.sendIpcMessage(message);
|
||||
|
||||
try {
|
||||
// Since we can not guarantee that a response message will ever be sent, we put a timeout
|
||||
@ -151,8 +148,56 @@ export default class IPCService {
|
||||
}
|
||||
}
|
||||
|
||||
private getSocket() {
|
||||
return NodeIPC.of[this.socketName];
|
||||
// As we're using the desktop_proxy to communicate with the native messaging directly,
|
||||
// the messages need to follow Native Messaging Host protocol (uint32 size followed by message).
|
||||
// https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging#native-messaging-host-protocol
|
||||
private sendIpcMessage(message: MessageCommon) {
|
||||
const messageStr = JSON.stringify(message);
|
||||
const buffer = Buffer.alloc(4 + messageStr.length);
|
||||
buffer.writeUInt32LE(messageStr.length, 0);
|
||||
buffer.write(messageStr, 4);
|
||||
|
||||
this.process?.stdin.write(buffer);
|
||||
}
|
||||
|
||||
private processIpcMessage(data: Buffer) {
|
||||
this.processOutputBuffer = Buffer.concat([this.processOutputBuffer, data]);
|
||||
|
||||
// We might receive more than one IPC message per data event, so we need to process them all
|
||||
// We continue as long as we have at least 4 + 1 bytes in the buffer, where the first 4 bytes
|
||||
// represent the message length and the 5th byte is the message
|
||||
while (this.processOutputBuffer.length > 4) {
|
||||
// Read the message length and ensure we have the full message
|
||||
const msgLength = this.processOutputBuffer.readUInt32LE(0);
|
||||
if (msgLength + 4 < this.processOutputBuffer.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the message from the buffer
|
||||
const messageStr = this.processOutputBuffer.subarray(4, msgLength + 4).toString();
|
||||
const message = JSON.parse(messageStr);
|
||||
|
||||
// Store the remaining buffer, which is part of the next message
|
||||
this.processOutputBuffer = this.processOutputBuffer.subarray(msgLength + 4);
|
||||
|
||||
// Process the connect/disconnect messages separately
|
||||
if (message?.command === "connected") {
|
||||
console.log("[IPCService] connected");
|
||||
this.connectionState = IPCConnectionState.Connected;
|
||||
|
||||
this.awaitingConnection.forEach((deferred) => {
|
||||
deferred.resolve(null);
|
||||
});
|
||||
this.awaitingConnection.clear();
|
||||
continue;
|
||||
} else if (message?.command === "disconnected") {
|
||||
console.log("[IPCService] disconnected");
|
||||
this.connectionState = IPCConnectionState.Disconnected;
|
||||
continue;
|
||||
}
|
||||
|
||||
this.processMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
private processMessage(message: any) {
|
||||
@ -172,3 +217,41 @@ export default class IPCService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function selectProxyPath(): string {
|
||||
const proxyExtension = process.platform === "win32" ? ".exe" : "";
|
||||
|
||||
// If the PROXY_PATH environment variable is set, use that
|
||||
if (process.env.PROXY_PATH) {
|
||||
if (!fs.existsSync(process.env.PROXY_PATH)) {
|
||||
throw new Error(`PROXY_PATH is set to ${process.env.PROXY_PATH} but the file does not exist`);
|
||||
}
|
||||
return process.env.PROXY_PATH;
|
||||
}
|
||||
|
||||
// Otherwise try the debug build if present
|
||||
const debugProxyPath = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"..",
|
||||
"desktop_native",
|
||||
"target",
|
||||
"debug",
|
||||
`desktop_proxy${proxyExtension}`,
|
||||
);
|
||||
if (fs.existsSync(debugProxyPath)) {
|
||||
return debugProxyPath;
|
||||
}
|
||||
|
||||
// On MacOS, try the release build (sandboxed)
|
||||
const macReleaseProxyPath = `/Applications/Bitwarden.app/Contents/MacOS/desktop_proxy${proxyExtension}`;
|
||||
if (process.platform === "darwin" && fs.existsSync(macReleaseProxyPath)) {
|
||||
return macReleaseProxyPath;
|
||||
}
|
||||
|
||||
throw new Error("Could not find the desktop_proxy executable");
|
||||
}
|
||||
|
@ -5,12 +5,17 @@
|
||||
"target": "es6",
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": false,
|
||||
"declaration": false,
|
||||
"paths": {
|
||||
"@src/*": ["src/*"],
|
||||
"@bitwarden/node/*": ["../../../libs/node/src/*"],
|
||||
"@bitwarden/common/*": ["../../../libs/common/src/*"]
|
||||
"@bitwarden/admin-console/*": ["../../../libs/admin-console/src/*"],
|
||||
"@bitwarden/auth/*": ["../../../libs/auth/src/*"],
|
||||
"@bitwarden/common/*": ["../../../libs/common/src/*"],
|
||||
"@bitwarden/key-management": ["../../../libs/key-management/src/"],
|
||||
"@bitwarden/node/*": ["../../../libs/node/src/*"]
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
|
70
package-lock.json
generated
70
package-lock.json
generated
@ -113,7 +113,6 @@
|
||||
"@types/node": "22.10.7",
|
||||
"@types/node-fetch": "2.6.4",
|
||||
"@types/node-forge": "1.3.11",
|
||||
"@types/node-ipc": "9.2.3",
|
||||
"@types/papaparse": "5.3.15",
|
||||
"@types/proper-lockfile": "4.1.4",
|
||||
"@types/retry": "0.12.5",
|
||||
@ -157,7 +156,6 @@
|
||||
"json5": "2.2.3",
|
||||
"lint-staged": "15.4.1",
|
||||
"mini-css-extract-plugin": "2.9.2",
|
||||
"node-ipc": "9.2.1",
|
||||
"postcss": "8.5.1",
|
||||
"postcss-loader": "8.1.1",
|
||||
"prettier": "3.4.2",
|
||||
@ -10047,16 +10045,6 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node-ipc": {
|
||||
"version": "9.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-ipc/-/node-ipc-9.2.3.tgz",
|
||||
"integrity": "sha512-/MvSiF71fYf3+zwqkh/zkVkZj1hl1Uobre9EMFy08mqfJNAmpR0vmPgOUdEIDVgifxHj6G1vYMPLSBLLxoDACQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node/node_modules/undici-types": {
|
||||
"version": "6.20.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||
@ -15862,16 +15850,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/easy-stack": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz",
|
||||
"integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
@ -17182,16 +17160,6 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/event-pubsub": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz",
|
||||
"integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==",
|
||||
"dev": true,
|
||||
"license": "Unlicense",
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/event-stream": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz",
|
||||
@ -21964,29 +21932,6 @@
|
||||
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/js-message": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz",
|
||||
"integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/js-queue": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.2.tgz",
|
||||
"integrity": "sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"easy-stack": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
@ -25710,21 +25655,6 @@
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/node-ipc": {
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.2.1.tgz",
|
||||
"integrity": "sha512-mJzaM6O3xHf9VT8BULvJSbdVbmHUKRNOH7zDDkCrA1/T+CVjq2WVIDfLt0azZRXpgArJtl3rtmEozrbXPZ9GaQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"event-pubsub": "4.3.0",
|
||||
"js-message": "1.0.7",
|
||||
"js-queue": "2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.18",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
|
||||
|
@ -74,7 +74,6 @@
|
||||
"@types/node": "22.10.7",
|
||||
"@types/node-fetch": "2.6.4",
|
||||
"@types/node-forge": "1.3.11",
|
||||
"@types/node-ipc": "9.2.3",
|
||||
"@types/papaparse": "5.3.15",
|
||||
"@types/proper-lockfile": "4.1.4",
|
||||
"@types/retry": "0.12.5",
|
||||
@ -118,7 +117,6 @@
|
||||
"json5": "2.2.3",
|
||||
"lint-staged": "15.4.1",
|
||||
"mini-css-extract-plugin": "2.9.2",
|
||||
"node-ipc": "9.2.1",
|
||||
"postcss": "8.5.1",
|
||||
"postcss-loader": "8.1.1",
|
||||
"prettier": "3.4.2",
|
||||
|
Loading…
Reference in New Issue
Block a user