mirror of
https://github.com/yume-chan/ya-webadb.git
synced 2025-10-03 09:49:24 +02:00
refactor: mark immutable array parameters as readonly
This commit is contained in:
parent
40a60ca112
commit
6873c03a9d
24 changed files with 89 additions and 60 deletions
|
@ -35,7 +35,7 @@ export const AdbDefaultInterfaceFilter = {
|
|||
} as const satisfies UsbInterfaceFilter;
|
||||
|
||||
export function mergeDefaultAdbInterfaceFilter(
|
||||
filters: USBDeviceFilter[] | undefined,
|
||||
filters: readonly USBDeviceFilter[] | undefined,
|
||||
): (USBDeviceFilter & UsbInterfaceFilter)[] {
|
||||
if (!filters || filters.length === 0) {
|
||||
return [AdbDefaultInterfaceFilter];
|
||||
|
|
|
@ -7,8 +7,8 @@ import { isErrorName, matchFilters } from "./utils.js";
|
|||
|
||||
export namespace AdbDaemonWebUsbDeviceManager {
|
||||
export interface RequestDeviceOptions {
|
||||
filters?: USBDeviceFilter[] | undefined;
|
||||
exclusionFilters?: USBDeviceFilter[] | undefined;
|
||||
filters?: readonly USBDeviceFilter[] | undefined;
|
||||
exclusionFilters?: readonly USBDeviceFilter[] | undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ export class AdbDaemonWebUsbDeviceManager {
|
|||
try {
|
||||
const device = await this.#usbManager.requestDevice({
|
||||
filters,
|
||||
exclusionFilters: options.exclusionFilters,
|
||||
exclusionFilters: options.exclusionFilters as USBDeviceFilter[],
|
||||
});
|
||||
|
||||
const interface_ = matchFilters(
|
||||
|
|
|
@ -25,8 +25,8 @@ export class AdbDaemonWebUsbDeviceObserver
|
|||
return new AdbDaemonWebUsbDeviceObserver(usb, devices, options);
|
||||
}
|
||||
|
||||
readonly #filters: (USBDeviceFilter & UsbInterfaceFilter)[];
|
||||
readonly #exclusionFilters?: USBDeviceFilter[] | undefined;
|
||||
readonly #filters: readonly (USBDeviceFilter & UsbInterfaceFilter)[];
|
||||
readonly #exclusionFilters?: readonly USBDeviceFilter[] | undefined;
|
||||
readonly #usbManager: USB;
|
||||
|
||||
readonly #onDeviceAdd = new EventEmitter<
|
||||
|
|
|
@ -80,7 +80,7 @@ export function getSerialNumber(device: USBDevice) {
|
|||
*
|
||||
* ADB interface only has two endpoints, one for input and one for output.
|
||||
*/
|
||||
export function findUsbEndpoints(endpoints: USBEndpoint[]) {
|
||||
export function findUsbEndpoints(endpoints: readonly USBEndpoint[]) {
|
||||
if (endpoints.length === 0) {
|
||||
throw new TypeError("No endpoints given");
|
||||
}
|
||||
|
@ -153,18 +153,18 @@ export function matchFilter(
|
|||
|
||||
export function matchFilters(
|
||||
device: USBDevice,
|
||||
filters: (USBDeviceFilter & UsbInterfaceFilter)[],
|
||||
exclusionFilters?: USBDeviceFilter[],
|
||||
filters: readonly (USBDeviceFilter & UsbInterfaceFilter)[],
|
||||
exclusionFilters?: readonly USBDeviceFilter[],
|
||||
): UsbInterfaceIdentifier | false;
|
||||
export function matchFilters(
|
||||
device: USBDevice,
|
||||
filters: USBDeviceFilter[],
|
||||
exclusionFilters?: USBDeviceFilter[],
|
||||
filters: readonly USBDeviceFilter[],
|
||||
exclusionFilters?: readonly USBDeviceFilter[],
|
||||
): boolean;
|
||||
export function matchFilters(
|
||||
device: USBDevice,
|
||||
filters: USBDeviceFilter[],
|
||||
exclusionFilters?: USBDeviceFilter[],
|
||||
filters: readonly USBDeviceFilter[],
|
||||
exclusionFilters?: readonly USBDeviceFilter[],
|
||||
): UsbInterfaceIdentifier | boolean {
|
||||
if (exclusionFilters && exclusionFilters.length > 0) {
|
||||
if (matchFilters(device, exclusionFilters)) {
|
||||
|
|
|
@ -57,9 +57,9 @@ function concatStreams<T>(...streams: ReadableStream<T>[]): ReadableStream<T> {
|
|||
}
|
||||
|
||||
export class AdbScrcpyExitedError extends Error {
|
||||
output: string[];
|
||||
output: readonly string[];
|
||||
|
||||
constructor(output: string[]) {
|
||||
constructor(output: readonly string[]) {
|
||||
super("scrcpy server exited prematurely");
|
||||
this.output = output;
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ export class Adb implements Closeable {
|
|||
}
|
||||
|
||||
rm(
|
||||
filenames: string | string[],
|
||||
filenames: string | readonly string[],
|
||||
options?: { recursive?: boolean; force?: boolean },
|
||||
): Promise<string> {
|
||||
const args = ["rm"];
|
||||
|
@ -144,10 +144,12 @@ export class Adb implements Closeable {
|
|||
}
|
||||
if (Array.isArray(filenames)) {
|
||||
for (const filename of filenames) {
|
||||
args.push(escapeArg(filename));
|
||||
// https://github.com/microsoft/typescript/issues/17002
|
||||
args.push(escapeArg(filename as string));
|
||||
}
|
||||
} else {
|
||||
args.push(escapeArg(filenames));
|
||||
// https://github.com/microsoft/typescript/issues/17002
|
||||
args.push(escapeArg(filenames as string));
|
||||
}
|
||||
// https://android.googlesource.com/platform/packages/modules/adb/+/1a0fb8846d4e6b671c8aa7f137a8c21d7b248716/client/adb_install.cpp#984
|
||||
args.push("</dev/null");
|
||||
|
|
|
@ -66,7 +66,7 @@ export class AdbBanner {
|
|||
return this.#device;
|
||||
}
|
||||
|
||||
readonly #features: AdbFeature[] = [];
|
||||
readonly #features: readonly AdbFeature[] = [];
|
||||
get features() {
|
||||
return this.#features;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ export class AdbBanner {
|
|||
product: string | undefined,
|
||||
model: string | undefined,
|
||||
device: string | undefined,
|
||||
features: AdbFeature[],
|
||||
features: readonly AdbFeature[],
|
||||
) {
|
||||
this.#product = product;
|
||||
this.#model = model;
|
||||
|
|
|
@ -28,7 +28,9 @@ export class AdbNoneProtocolSubprocessService extends AdbNoneProtocolSpawner {
|
|||
this.#adb = adb;
|
||||
}
|
||||
|
||||
async pty(command?: string | string[]): Promise<AdbNoneProtocolPtyProcess> {
|
||||
async pty(
|
||||
command?: string | readonly string[],
|
||||
): Promise<AdbNoneProtocolPtyProcess> {
|
||||
if (command === undefined) {
|
||||
command = "";
|
||||
} else if (Array.isArray(command)) {
|
||||
|
@ -36,7 +38,8 @@ export class AdbNoneProtocolSubprocessService extends AdbNoneProtocolSpawner {
|
|||
}
|
||||
|
||||
return new AdbNoneProtocolPtyProcess(
|
||||
await this.#adb.createSocket(`shell:${command}`),
|
||||
// https://github.com/microsoft/typescript/issues/17002
|
||||
await this.#adb.createSocket(`shell:${command as string}`),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,13 +28,13 @@ export interface AdbNoneProtocolProcess {
|
|||
|
||||
export class AdbNoneProtocolSpawner {
|
||||
readonly #spawn: (
|
||||
command: string[],
|
||||
command: readonly string[],
|
||||
signal: AbortSignal | undefined,
|
||||
) => Promise<AdbNoneProtocolProcess>;
|
||||
|
||||
constructor(
|
||||
spawn: (
|
||||
command: string[],
|
||||
command: readonly string[],
|
||||
signal: AbortSignal | undefined,
|
||||
) => Promise<AdbNoneProtocolProcess>,
|
||||
) {
|
||||
|
@ -42,7 +42,7 @@ export class AdbNoneProtocolSpawner {
|
|||
}
|
||||
|
||||
spawn(
|
||||
command: string | string[],
|
||||
command: string | readonly string[],
|
||||
signal?: AbortSignal,
|
||||
): Promise<AdbNoneProtocolProcess> {
|
||||
signal?.throwIfAborted();
|
||||
|
@ -54,12 +54,12 @@ export class AdbNoneProtocolSpawner {
|
|||
return this.#spawn(command, signal);
|
||||
}
|
||||
|
||||
async spawnWait(command: string | string[]): Promise<Uint8Array> {
|
||||
async spawnWait(command: string | readonly string[]): Promise<Uint8Array> {
|
||||
const process = await this.spawn(command);
|
||||
return await process.output.pipeThrough(new ConcatBufferStream());
|
||||
}
|
||||
|
||||
async spawnWaitText(command: string | string[]): Promise<string> {
|
||||
async spawnWaitText(command: string | readonly string[]): Promise<string> {
|
||||
const process = await this.spawn(command);
|
||||
return await process.output
|
||||
.pipeThrough(new TextDecoderStream())
|
||||
|
|
|
@ -32,7 +32,7 @@ export class AdbShellProtocolSubprocessService extends AdbShellProtocolSpawner {
|
|||
}
|
||||
|
||||
async pty(options?: {
|
||||
command?: string | string[] | undefined;
|
||||
command?: string | readonly string[] | undefined;
|
||||
terminalType?: string;
|
||||
}): Promise<AdbShellProtocolPtyProcess> {
|
||||
let service = "shell,v2,pty";
|
||||
|
|
|
@ -26,13 +26,13 @@ export interface AdbShellProtocolProcess {
|
|||
|
||||
export class AdbShellProtocolSpawner {
|
||||
readonly #spawn: (
|
||||
command: string[],
|
||||
command: readonly string[],
|
||||
signal: AbortSignal | undefined,
|
||||
) => Promise<AdbShellProtocolProcess>;
|
||||
|
||||
constructor(
|
||||
spawn: (
|
||||
command: string[],
|
||||
command: readonly string[],
|
||||
signal: AbortSignal | undefined,
|
||||
) => Promise<AdbShellProtocolProcess>,
|
||||
) {
|
||||
|
@ -40,7 +40,7 @@ export class AdbShellProtocolSpawner {
|
|||
}
|
||||
|
||||
spawn(
|
||||
command: string | string[],
|
||||
command: string | readonly string[],
|
||||
signal?: AbortSignal,
|
||||
): Promise<AdbShellProtocolProcess> {
|
||||
signal?.throwIfAborted();
|
||||
|
@ -53,7 +53,7 @@ export class AdbShellProtocolSpawner {
|
|||
}
|
||||
|
||||
async spawnWait(
|
||||
command: string | string[],
|
||||
command: string | readonly string[],
|
||||
): Promise<AdbShellProtocolSpawner.WaitResult<Uint8Array>> {
|
||||
const process = await this.spawn(command);
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
|
@ -65,7 +65,7 @@ export class AdbShellProtocolSpawner {
|
|||
}
|
||||
|
||||
async spawnWaitText(
|
||||
command: string | string[],
|
||||
command: string | readonly string[],
|
||||
): Promise<AdbShellProtocolSpawner.WaitResult<string>> {
|
||||
const process = await this.spawn(command);
|
||||
const [stdout, stderr, exitCode] = await Promise.all([
|
||||
|
|
|
@ -139,7 +139,7 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
|
|||
};
|
||||
};
|
||||
|
||||
export const ADB_DEFAULT_AUTHENTICATORS: AdbAuthenticator[] = [
|
||||
export const ADB_DEFAULT_AUTHENTICATORS: readonly AdbAuthenticator[] = [
|
||||
AdbSignatureAuthenticator,
|
||||
AdbPublicKeyAuthenticator,
|
||||
];
|
||||
|
|
|
@ -49,7 +49,7 @@ export const ADB_DAEMON_DEFAULT_FEATURES = /* #__PURE__ */ (() =>
|
|||
"sendrecv_v2_zstd",
|
||||
"sendrecv_v2_dry_run_send",
|
||||
AdbFeature.DelayedAck,
|
||||
] as AdbFeature[])();
|
||||
] as readonly AdbFeature[])();
|
||||
export const ADB_DAEMON_DEFAULT_INITIAL_PAYLOAD_SIZE = 32 * 1024 * 1024;
|
||||
|
||||
export type AdbDaemonConnection = ReadableWritablePair<
|
||||
|
@ -61,7 +61,7 @@ export interface AdbDaemonAuthenticationOptions {
|
|||
serial: string;
|
||||
connection: AdbDaemonConnection;
|
||||
credentialStore: AdbCredentialStore;
|
||||
authenticators?: AdbAuthenticator[];
|
||||
authenticators?: readonly AdbAuthenticator[];
|
||||
features?: readonly AdbFeature[];
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,7 +39,7 @@ export class AdbServerClient {
|
|||
|
||||
static parseDeviceList(
|
||||
value: string,
|
||||
includeStates: AdbServerClient.ConnectionState[] = [
|
||||
includeStates: readonly AdbServerClient.ConnectionState[] = [
|
||||
"device",
|
||||
"unauthorized",
|
||||
],
|
||||
|
@ -201,7 +201,7 @@ export class AdbServerClient {
|
|||
* Equivalent ADB Command: `adb devices -l`
|
||||
*/
|
||||
async getDevices(
|
||||
includeStates: AdbServerClient.ConnectionState[] = [
|
||||
includeStates: readonly AdbServerClient.ConnectionState[] = [
|
||||
"device",
|
||||
"unauthorized",
|
||||
],
|
||||
|
@ -249,7 +249,7 @@ export class AdbServerClient {
|
|||
*/
|
||||
async getDeviceFeatures(
|
||||
device: AdbServerClient.DeviceSelector,
|
||||
): Promise<{ transportId: bigint; features: AdbFeature[] }> {
|
||||
): Promise<{ transportId: bigint; features: readonly AdbFeature[] }> {
|
||||
// On paper, `host:features` is a host service (device features are cached in host),
|
||||
// so it shouldn't use `createDeviceConnection`,
|
||||
// which is used to forward the service to the device.
|
||||
|
|
|
@ -14,7 +14,7 @@ export function unorderedRemove<T>(array: T[], index: number) {
|
|||
}
|
||||
|
||||
interface Observer {
|
||||
includeStates: AdbServerClient.ConnectionState[];
|
||||
includeStates: readonly AdbServerClient.ConnectionState[];
|
||||
onDeviceAdd: EventEmitter<readonly AdbServerClient.Device[]>;
|
||||
onDeviceRemove: EventEmitter<readonly AdbServerClient.Device[]>;
|
||||
onListChange: EventEmitter<readonly AdbServerClient.Device[]>;
|
||||
|
@ -23,7 +23,7 @@ interface Observer {
|
|||
|
||||
function filterDeviceStates(
|
||||
devices: readonly AdbServerClient.Device[],
|
||||
states: AdbServerClient.ConnectionState[],
|
||||
states: readonly AdbServerClient.ConnectionState[],
|
||||
) {
|
||||
return devices.filter((device) => states.includes(device.state));
|
||||
}
|
||||
|
@ -214,6 +214,6 @@ export class AdbServerDeviceObserverOwner {
|
|||
|
||||
export namespace AdbServerDeviceObserverOwner {
|
||||
export interface Options extends AdbServerClient.ServerConnectionOptions {
|
||||
includeStates?: AdbServerClient.ConnectionState[];
|
||||
includeStates?: readonly AdbServerClient.ConnectionState[];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ export const ADB_SERVER_DEFAULT_FEATURES = /* #__PURE__ */ (() =>
|
|||
"sendrecv_v2_lz4",
|
||||
"sendrecv_v2_zstd",
|
||||
"sendrecv_v2_dry_run_send",
|
||||
] as AdbFeature[])();
|
||||
] as readonly AdbFeature[])();
|
||||
|
||||
export class AdbServerTransport implements AdbTransport {
|
||||
#client: AdbServerClient;
|
||||
|
|
|
@ -5,7 +5,7 @@ export interface AdbBackupOptions {
|
|||
user: number;
|
||||
saveSharedStorage?: boolean;
|
||||
saveWidgets?: boolean;
|
||||
packages: string[] | "user" | "all";
|
||||
packages: readonly string[] | "user" | "all";
|
||||
savePackageApk: boolean;
|
||||
savePackageObb: boolean;
|
||||
savePackageKeyValue: boolean;
|
||||
|
|
|
@ -53,8 +53,9 @@ export class CmdNoneProtocolService extends AdbNoneProtocolSpawner {
|
|||
throw new Error("Unsupported");
|
||||
}
|
||||
|
||||
command[0] = fallback;
|
||||
return adb.subprocess.noneProtocol.spawn(command);
|
||||
const fallbackCommand = command.slice();
|
||||
fallbackCommand[0] = fallback;
|
||||
return adb.subprocess.noneProtocol.spawn(fallbackCommand);
|
||||
});
|
||||
|
||||
this.#supportsCmd = adb.canUseFeature(AdbFeature.Cmd);
|
||||
|
@ -116,8 +117,9 @@ export class CmdShellProtocolService extends AdbShellProtocolSpawner {
|
|||
throw new Error("Unsupported");
|
||||
}
|
||||
|
||||
command[0] = fallback;
|
||||
return adb.subprocess.shellProtocol.spawn(command);
|
||||
const fallbackCommand = command.slice();
|
||||
fallbackCommand[0] = fallback;
|
||||
return adb.subprocess.shellProtocol.spawn(fallbackCommand);
|
||||
});
|
||||
|
||||
this.#adb = adb;
|
||||
|
|
|
@ -90,7 +90,7 @@ export interface LogcatFormatModifiers {
|
|||
export interface LogcatOptions {
|
||||
dump?: boolean | undefined;
|
||||
pid?: number | undefined;
|
||||
ids?: LogId[] | undefined;
|
||||
ids?: readonly LogId[] | undefined;
|
||||
tail?: number | Date | undefined;
|
||||
}
|
||||
|
||||
|
@ -415,7 +415,7 @@ export class Logcat extends AdbServiceBase {
|
|||
return LogId[key as keyof typeof LogId];
|
||||
}
|
||||
|
||||
static joinLogId(ids: LogId[]): string {
|
||||
static joinLogId(ids: readonly LogId[]): string {
|
||||
return ids.map((id) => Logcat.logIdToName(id)).join(",");
|
||||
}
|
||||
|
||||
|
@ -434,7 +434,7 @@ export class Logcat extends AdbServiceBase {
|
|||
static readonly LOG_SIZE_REGEX_11: RegExp =
|
||||
/(.*): ring buffer is (.*) (.*)B \((.*) (.*)B consumed, (.*) (.*)B readable\), max entry is (.*) B, max payload is (.*) B/;
|
||||
|
||||
async getLogSize(ids?: LogId[]): Promise<LogSize[]> {
|
||||
async getLogSize(ids?: readonly LogId[]): Promise<LogSize[]> {
|
||||
const process = await this.adb.subprocess.noneProtocol.spawn([
|
||||
"logcat",
|
||||
"-g",
|
||||
|
@ -488,7 +488,7 @@ export class Logcat extends AdbServiceBase {
|
|||
return result;
|
||||
}
|
||||
|
||||
async clear(ids?: LogId[]): Promise<void> {
|
||||
async clear(ids?: readonly LogId[]): Promise<void> {
|
||||
const args = ["logcat", "-c"];
|
||||
if (ids && ids.length > 0) {
|
||||
args.push("-b", Logcat.joinLogId(ids));
|
||||
|
|
|
@ -81,7 +81,7 @@ export class OverlayDisplay extends AdbServiceBase {
|
|||
}));
|
||||
}
|
||||
|
||||
async set(devices: OverlayDisplayDevice[]): Promise<void> {
|
||||
async set(devices: readonly OverlayDisplayDevice[]): Promise<void> {
|
||||
await this.#settings.put(
|
||||
"global",
|
||||
OverlayDisplay.SETTING_KEY,
|
||||
|
|
|
@ -231,7 +231,7 @@ export interface PackageManagerUninstallOptions {
|
|||
*
|
||||
* On Android 10 and lower, only one split name can be specified.
|
||||
*/
|
||||
splitNames: string[];
|
||||
splitNames: readonly string[];
|
||||
}
|
||||
|
||||
const PACKAGE_MANAGER_UNINSTALL_OPTIONS_MAP: Record<
|
||||
|
@ -298,7 +298,7 @@ export class PackageManager extends AdbServiceBase {
|
|||
* @param apks Path to the apk file. It must exist on the device. On Android 10 and lower, only one apk can be specified.
|
||||
*/
|
||||
async install(
|
||||
apks: string[],
|
||||
apks: readonly string[],
|
||||
options?: Partial<PackageManagerInstallOptions>,
|
||||
): Promise<string> {
|
||||
const args = buildInstallArguments("install", options);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
export class ParseError extends Error {
|
||||
#expected: string[];
|
||||
#expected: readonly string[];
|
||||
|
||||
get expected(): string[] {
|
||||
get expected(): readonly string[] {
|
||||
return this.#expected;
|
||||
}
|
||||
|
||||
constructor(expected: string[]) {
|
||||
constructor(expected: readonly string[]) {
|
||||
super(`Expected ${expected.join(", ")}`);
|
||||
this.#expected = expected;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
export function buildArguments<T>(
|
||||
commands: string[],
|
||||
commands: readonly string[],
|
||||
options: Partial<T> | undefined,
|
||||
map: Partial<Record<keyof T, string>>,
|
||||
): string[] {
|
||||
const args = commands;
|
||||
const args = commands.slice();
|
||||
if (options) {
|
||||
for (const [key, value] of Object.entries(options)) {
|
||||
if (value) {
|
||||
|
|
22
libraries/stream-extra/src/consumable.spec.ts
Normal file
22
libraries/stream-extra/src/consumable.spec.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import assert from "node:assert";
|
||||
import { describe, it } from "node:test";
|
||||
|
||||
import { Consumable } from "./consumable.js";
|
||||
|
||||
describe("Consumable", () => {
|
||||
it("should export all symbols", () => {
|
||||
assert(!!Consumable.WritableStream, "WritableStream should be define");
|
||||
|
||||
assert(
|
||||
!!Consumable.WrapWritableStream,
|
||||
"WrapWritableStream should be define",
|
||||
);
|
||||
|
||||
assert(!!Consumable.ReadableStream, "ReadableStream should be define");
|
||||
|
||||
assert(
|
||||
!!Consumable.WrapByteReadableStream,
|
||||
"WrapByteReadableStream should be define",
|
||||
);
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue