Upgrade from 2.0.0
This page lists changes from version 2.0.0 in core packages.
For changes in Scrcpy-related packages, see this page.
@yume-chan/adb
Breaking: Renamed AdbCredentialStore to AdbCredentialManager
The credential store interface has been renamed from AdbCredentialStore to AdbCredentialManager to better reflect its role in credential management. The old interface has been completely removed.
Migration guide:
- Replace all imports of
AdbCredentialStorewithAdbCredentialManager - Replace all usages of
AdbCredentialStorewithAdbCredentialManager - The interface API remains the same, so only import/type name changes are required
Before:
import type { AdbCredentialStore } from "@yume-chan/adb-credential-web";
const store: AdbCredentialStore = ...;
After:
import type { AdbCredentialManager } from "@yume-chan/adb-credential-web";
const store: AdbCredentialManager = ...;
Server client can filter devices by state
AdbServerClient.prototype.getDevices and AdbServerClient.prototype.trackDevices now accept an optional includeStates parameter.
It can be an array of AdbServerClient.ConnectionState, i.e., "unauthorized" | "offline" | "device"
The default value is ["unauthorized", "device"] for backward compatibility. In a future major version, the default value will be changed to ["unauthorized", "offline", "device"].
- JavaScript
- TypeScript
const devices = await client.getDevices(["unauthorized", "offline", "device"]);
const observer = await client.trackDevices({
includeStates: ["unauthorized", "offline", "device"],
});
import type { AdbServerClient } from "@yume-chan/adb";
declare const client: AdbServerClient;
const devices: AdbServerClient.Device[] = await client.getDevices([
"unauthorized",
"offline",
"device",
]);
const observer = await client.trackDevices({
includeStates: ["unauthorized", "offline", "device"],
});
Add device state to AdbServerClient.Device
To comply with the new API, AdbServerClient.Device now has a state property.
The old authenticating property is deprecated, and will be removed in a future major version. It now only returns true when state is "unauthorized".
- JavaScript
- TypeScript
console.log(device.state); // "unauthorized" | "offline" | "device"
console.log(device.authenticating); // `true` when `device.state === "unauthorized"`
import type { AdbServerClient } from "@yume-chan/adb";
declare const device: AdbServerClient.Device;
console.log(device.state); // "unauthorized" | "offline" | "device"
console.log(device.authenticating); // `true` when `device.state === "unauthorized"`
Subprocess spawnWait and spawnWaitText methods has been moved to method chaining
- JavaScript
- TypeScript
// Before
const output = await adb.subprocess.noneProtocol.spawnWait("ls -al /");
// After
const output = await adb.subprocess.noneProtocol.spawn("ls -al /").wait();
// Before
const output = await adb.subprocess.noneProtocol.spawnWaitText("ls -al /");
// After
const output = await adb.subprocess.noneProtocol.spawn("ls -al /").wait().toString();
import type { Adb } from "@yume-chan/adb";
declare const adb: Adb;
// Before
const output = await adb.subprocess.noneProtocol.spawnWait("ls -al /");
// After
const output = await adb.subprocess.noneProtocol.spawn("ls -al /").wait();
// Before
const output = await adb.subprocess.noneProtocol.spawnWaitText("ls -al /");
// After
const output = await adb.subprocess.noneProtocol.spawn("ls -al /").wait().toString();
The wait method now accepts a ReadableStream for stdin:
- JavaScript
- TypeScript
import { ReadableStream } from "@yume-chan/stream-extra";
const output = await adb.subprocess.shellProtocol.spawn("cat").wait({
stdin: new ReadableStream({
start(controller) {
controller.enqueue(encodeUtf8("Hello World!"));
controller.close();
},
}),
});
import type { Adb } from "@yume-chan/adb";
import { ReadableStream } from "@yume-chan/stream-extra";
declare const adb: Adb;
const output = await adb.subprocess.shellProtocol!.spawn("cat").wait({
stdin: new ReadableStream<Uint8Array>({
start(controller) {
controller.enqueue(encodeUtf8("Hello World!"));
controller.close();
},
}),
});
Breaking: PTY Type Renaming
The PTY types have been renamed to simplify the naming convention. The main interface AdbPtyProcess has been renamed to AdbPty, and the specific implementations have also been renamed:
AdbNoneProtocolPtyProcess→AdbNoneProtocolPtyAdbShellProtocolPtyProcess→AdbShellProtocolPty
Migration guide:
- Replace all imports and references to
AdbPtyProcesswithAdbPty - Replace all imports and references to
AdbNoneProtocolPtyProcesswithAdbNoneProtocolPty - Replace all imports and references to
AdbShellProtocolPtyProcesswithAdbShellProtocolPty
Before:
import type { AdbPtyProcess } from "@yume-chan/adb";
// Using old PTY process
const pty: AdbPtyProcess = await adb.subprocess.shellProtocol.pty({
command: ["bash"],
});
After:
import type {
AdbPty,
AdbNoneProtocolPty,
AdbShellProtocolPty,
} from "@yume-chan/adb";
// Using new PTY interface
const pty: AdbPty = await adb.subprocess.shellProtocol.pty({
command: ["bash"],
});
Shell protocol raw mode now supports closing stdin
Shell protocol in raw mode is the only combination that supports closing stdin. Some programs (like cat) might rely on this behavior to properly function.
When using spawn, stdin can be closed by closing the WritableStream:
- JavaScript
- TypeScript
import { encodeUtf8 } from "@yume-chan/adb";
const process = await adb.subprocess.shellProtocol.spawn("cat");
const writer = process.stdin.getWriter();
await writer.write(encodeUtf8("Hello World!"));
await writer.close();
import type { Adb } from "@yume-chan/adb";
import { encodeUtf8 } from "@yume-chan/adb";
declare const adb: Adb;
const process = await adb.subprocess.shellProtocol!.spawn("cat");
const writer = process.stdin.getWriter();
await writer.write(encodeUtf8("Hello World!"));
await writer.close();
When using spawn.wait, stdin can be closed by closing the ReadableStream:
- JavaScript
- TypeScript
import { encodeUtf8 } from "@yume-chan/adb";
import { ReadableStream } from "@yume-chan/stream-extra";
const output = await adb.subprocess.shellProtocol.spawn("cat").wait({
stdin: new ReadableStream({
start(controller) {
controller.enqueue(encodeUtf8("Hello World!"));
controller.close();
},
}),
});
import type { Adb } from "@yume-chan/adb";
import { encodeUtf8 } from "@yume-chan/adb";
import { ReadableStream } from "@yume-chan/stream-extra";
declare const adb: Adb;
const output = await adb.subprocess.shellProtocol!.spawn("cat").wait({
stdin: new ReadableStream<Uint8Array>({
start(controller) {
controller.enqueue(encodeUtf8("Hello World!"));
controller.close();
},
}),
});
@yume-chan/adb-credential-web
Breaking: AdbWebCredentialStore replaced by AdbWebCryptoCredentialManager
The legacy AdbWebCredentialStore class has been completely removed and replaced with the new modular architecture. Users must migrate to the new AdbWebCryptoCredentialManager with a TangoKeyStorage implementation.
Migration guide:
- Replace
new AdbWebCredentialStore()withnew AdbWebCryptoCredentialManager(storage) - Choose an appropriate storage implementation:
TangoIndexedDbStorage: Uses IndexedDB for storing multiple keys with unlimited capacity, supports Web WorkersTangoLocalStorage: Uses browser localStorage for simple single-key storageTangoPasswordProtectedStorage: Provides password-based encryption for stored keys (requires an underlying storage)TangoPrfStorage: Uses WebAuthn PRF extension for multi-factor authentication (requires an underlying storage)
Before:
import AdbWebCredentialStore from "@yume-chan/adb-credential-web";
const store = new AdbWebCredentialStore();
After:
import {
AdbWebCryptoCredentialManager,
TangoIndexedDbStorage,
} from "@yume-chan/adb-credential-web";
const storage = new TangoIndexedDbStorage();
const credentialManager = new AdbWebCryptoCredentialManager(storage);
@yume-chan/adb-credential-nodejs
Added TangoNodeStorage class
Added TangoNodeStorage class which is a Node.js ADB key storage manager that implements the TangoKeyStorage interface. It supports all Google ADB key storage conventions including:
- File-based storage compatible with Google ADB format (
~/.android/adbkey) - Secure file permissions (0o600 for private keys, 0o644 for public keys)
- Automatic directory creation and username generation using
username@hostnameformat - ADB_VENDOR_KEYS environment variable support for additional vendor keys
- Proper PEM format handling with both strict and lax format parsing
- Custom error types for robust key management (
KeyError,InvalidKeyError,VendorKeyError)
See documentation page TangoNodeStorage for more details and usages.
@yume-chan/adb-daemon-webusb
Fixed WebUSB SharedArrayBuffer Issue
Fixed an issue where WebUSB transfers would fail when using SharedArrayBuffer. The problem occurred because WebUSB doesn't support SharedArrayBuffer directly, which could cause connection failures.
Fix: Added conversion to local Uint8Array before WebUSB transfer using toLocalUint8Array() function.
Fixed WebUSB Connection Event Handling
Fixed an issue where device observers would lose track of manually selected devices. When a device was selected via navigator.usb.requestDevice(), Chrome wouldn't fire a "connect" event, causing device observers to miss the device.
Fix: Now manually dispatches a connect event after successful device selection to notify observers.
@yume-chan/adb-server-node-tcp
New constructor signatures for AdbServerNodeTcpConnector
The AdbServerNodeTcpConnector class has been completely rewritten with new constructor signatures and functionality, replacing the old API entirely.
Migration guide:
- The old constructor that only accepted
SocketConnectOptsdirectly has been replaced - The new constructor supports multiple parameter types: no parameters, string specifications, TCP socket options, and IPC socket options
Before:
import { AdbServerNodeTcpConnector } from "@yume-chan/adb-server-node-tcp";
// Old constructor only accepted SocketConnectOpts directly
const connector = new AdbServerNodeTcpConnector({
host: "localhost",
port: 5037,
});
After:
import { AdbServerNodeTcpConnector } from "@yume-chan/adb-server-node-tcp";
// New constructor supports multiple parameter types:
// 1. No parameters - uses environment variables or defaults
const connector1 = new AdbServerNodeTcpConnector();
// 2. String specification
const connector2 = new AdbServerNodeTcpConnector("tcp:localhost:5037");
// 3. TCP socket options with optional port
const connector3 = new AdbServerNodeTcpConnector({
host: "localhost",
port: 5037,
});
// 4. IPC socket options (Unix domain sockets)
const connector4 = new AdbServerNodeTcpConnector({ path: "/path/to/socket" });
Environment Variable Support
Added support for ADB environment variables that automatically reads ADB_SERVER_SOCKET, ANDROID_ADB_SERVER_ADDRESS, and ANDROID_ADB_SERVER_PORT environment variables.
Usage:
// Automatically uses environment variables if set:
// ADB_SERVER_SOCKET - full socket specification
// ANDROID_ADB_SERVER_ADDRESS - server address
// ANDROID_ADB_SERVER_PORT - server port
process.env.ADB_SERVER_SOCKET = "tcp:192.168.1.100:5037";
const connector = new AdbServerNodeTcpConnector(); // Will use env var