@yume-chan/android-bin 0.0.19 → 0.0.21

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.
Files changed (61) hide show
  1. package/CHANGELOG.json +36 -0
  2. package/CHANGELOG.md +19 -1
  3. package/LICENSE +21 -0
  4. package/esm/bu.d.ts +20 -7
  5. package/esm/bu.d.ts.map +1 -1
  6. package/esm/bu.js +47 -8
  7. package/esm/bu.js.map +1 -1
  8. package/esm/bug-report.d.ts +82 -21
  9. package/esm/bug-report.d.ts.map +1 -1
  10. package/esm/bug-report.js +189 -55
  11. package/esm/bug-report.js.map +1 -1
  12. package/esm/cmd.d.ts +4 -6
  13. package/esm/cmd.d.ts.map +1 -1
  14. package/esm/cmd.js +39 -24
  15. package/esm/cmd.js.map +1 -1
  16. package/esm/demo-mode.d.ts +3 -3
  17. package/esm/demo-mode.d.ts.map +1 -1
  18. package/esm/demo-mode.js +14 -15
  19. package/esm/demo-mode.js.map +1 -1
  20. package/esm/dumpsys.d.ts +21 -0
  21. package/esm/dumpsys.d.ts.map +1 -0
  22. package/esm/dumpsys.js +82 -0
  23. package/esm/dumpsys.js.map +1 -0
  24. package/esm/index.d.ts +3 -0
  25. package/esm/index.d.ts.map +1 -1
  26. package/esm/index.js +3 -0
  27. package/esm/index.js.map +1 -1
  28. package/esm/logcat.d.ts +3 -2
  29. package/esm/logcat.d.ts.map +1 -1
  30. package/esm/logcat.js +34 -24
  31. package/esm/logcat.js.map +1 -1
  32. package/esm/overlay-display.d.ts +20 -3
  33. package/esm/overlay-display.d.ts.map +1 -1
  34. package/esm/overlay-display.js +34 -61
  35. package/esm/overlay-display.js.map +1 -1
  36. package/esm/pm.d.ts +25 -2
  37. package/esm/pm.d.ts.map +1 -1
  38. package/esm/pm.js +88 -17
  39. package/esm/pm.js.map +1 -1
  40. package/esm/settings.d.ts +21 -8
  41. package/esm/settings.d.ts.map +1 -1
  42. package/esm/settings.js +55 -19
  43. package/esm/settings.js.map +1 -1
  44. package/esm/string-format.d.ts +40 -0
  45. package/esm/string-format.d.ts.map +1 -0
  46. package/esm/string-format.js +153 -0
  47. package/esm/string-format.js.map +1 -0
  48. package/package.json +13 -8
  49. package/src/bu.ts +68 -14
  50. package/src/bug-report.ts +236 -70
  51. package/src/cmd.ts +67 -33
  52. package/src/demo-mode.ts +47 -43
  53. package/src/dumpsys.ts +91 -0
  54. package/src/index.ts +3 -0
  55. package/src/logcat.ts +63 -74
  56. package/src/overlay-display.ts +82 -85
  57. package/src/pm.ts +149 -27
  58. package/src/settings.ts +99 -50
  59. package/src/string-format.ts +199 -0
  60. package/tsconfig.build.json +11 -0
  61. package/tsconfig.build.tsbuildinfo +1 -1
@@ -0,0 +1,40 @@
1
+ export declare class ParseError extends Error {
2
+ #private;
3
+ get expected(): string[];
4
+ constructor(expected: string[]);
5
+ }
6
+ export interface Reader {
7
+ value: string;
8
+ position: number;
9
+ }
10
+ export interface Format<T> {
11
+ parse(reader: Reader): T;
12
+ stringify(value: T): string;
13
+ }
14
+ type UnionResult<T extends readonly Format<unknown>[]> = Exclude<{
15
+ [K in keyof T]: T[K] extends Format<infer F> ? F : never;
16
+ }[number], undefined>;
17
+ type SequenceResult<T extends readonly (Format<unknown> | {
18
+ name: string;
19
+ format: Format<unknown>;
20
+ })[]> = {
21
+ [K in keyof T as K extends `${number}` ? T[K] extends {
22
+ name: infer N extends string;
23
+ } ? N : never : never]: T[K] extends {
24
+ format: Format<infer F>;
25
+ } ? F : never;
26
+ } extends infer R extends Record<string, unknown> ? R : never;
27
+ export declare const p: {
28
+ literal: <T extends string>(value: T) => Format<T>;
29
+ digits: () => Format<number>;
30
+ union: <const T_1 extends readonly Format<unknown>[]>(...args: T_1) => Format<Exclude<{ [K in keyof T_1]: T_1[K] extends Format<infer F> ? F : never; }[number], undefined>>;
31
+ separated: <T_2>(separator: string, format: Format<T_2>, min?: number, max?: number) => Format<T_2[]>;
32
+ repeated: <T_3>(format: Format<T_3>) => Format<T_3[]>;
33
+ sequence: <const T_4 extends readonly (Format<unknown> | {
34
+ name: string;
35
+ format: Format<unknown>;
36
+ })[]>(...args: T_4) => Format<SequenceResult<T_4>>;
37
+ map: <T_5, R>(format: Format<T_5>, map: (value: T_5) => R, reverse: (value: R) => T_5) => Format<R>;
38
+ };
39
+ export {};
40
+ //# sourceMappingURL=string-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string-format.d.ts","sourceRoot":"","sources":["../src/string-format.ts"],"names":[],"mappings":"AACA,qBAAa,UAAW,SAAQ,KAAK;;IAGjC,IAAI,QAAQ,IAAI,MAAM,EAAE,CAEvB;gBAEW,QAAQ,EAAE,MAAM,EAAE;CAIjC;AAED,MAAM,WAAW,MAAM;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,MAAM,CAAC,CAAC;IACrB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC;IACzB,SAAS,CAAC,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC;CAC/B;AAED,KAAK,WAAW,CAAC,CAAC,SAAS,SAAS,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,OAAO,CAC5D;KACK,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK;CAC3D,CAAC,MAAM,CAAC,EACT,SAAS,CACZ,CAAC;AAEF,KAAK,cAAc,CACf,CAAC,SAAS,SAAS,CACb,MAAM,CAAC,OAAO,CAAC,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;CAAE,CAC9C,EAAE,IACH;KACC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,GAAG,MAAM,EAAE,GAChC,CAAC,CAAC,CAAC,CAAC,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC,SAAS,MAAM,CAAA;KAAE,GACzC,CAAC,GACD,KAAK,GACT,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;KAAE,GAAG,CAAC,GAAG,KAAK;CACrE,SAAS,MAAM,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3C,CAAC,GACD,KAAK,CAAC;AAEZ,eAAO,MAAM,CAAC;;kBAaE,OAAO,MAAM,CAAC;;gCA6CX,MAAM;;;cAsDH,MAAM;gBAAU,OAAO,OAAO,CAAC;;;CAwCU,CAAC"}
@@ -0,0 +1,153 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
2
+ export class ParseError extends Error {
3
+ #expected;
4
+ get expected() {
5
+ return this.#expected;
6
+ }
7
+ constructor(expected) {
8
+ super(`Expected ${expected.join(", ")}`);
9
+ this.#expected = expected;
10
+ }
11
+ }
12
+ export const p = {
13
+ literal: (value) => ({
14
+ parse(reader) {
15
+ if (!reader.value.startsWith(value, reader.position)) {
16
+ throw new ParseError([value.charAt(0)]);
17
+ }
18
+ reader.position += value.length;
19
+ return value;
20
+ },
21
+ stringify() {
22
+ return value;
23
+ },
24
+ }),
25
+ digits: () => ({
26
+ parse(reader) {
27
+ const match = reader.value.substring(reader.position).match(/^\d+/);
28
+ if (!match) {
29
+ throw new ParseError("0123456789".split(""));
30
+ }
31
+ reader.position += match[0].length;
32
+ return Number.parseInt(match[0], 10);
33
+ },
34
+ stringify(value) {
35
+ return value.toString();
36
+ },
37
+ }),
38
+ union: (...args) => ({
39
+ parse(reader) {
40
+ const expected = [];
41
+ for (const format of args) {
42
+ try {
43
+ return format.parse(reader);
44
+ }
45
+ catch (e) {
46
+ if (e instanceof ParseError) {
47
+ expected.push(...e.expected);
48
+ }
49
+ else {
50
+ throw e;
51
+ }
52
+ }
53
+ }
54
+ throw new ParseError(expected);
55
+ },
56
+ stringify(value) {
57
+ for (const format of args) {
58
+ try {
59
+ const result = format.stringify(value);
60
+ // Parse the result to make sure it is valid
61
+ format.parse({ value: result, position: 0 });
62
+ }
63
+ catch (e) {
64
+ // ignore
65
+ }
66
+ }
67
+ throw new Error("No format matches");
68
+ },
69
+ }),
70
+ separated: (separator, format, min = 0, max = Infinity) => ({
71
+ parse(reader) {
72
+ const result = [];
73
+ while (true) {
74
+ try {
75
+ result.push(format.parse(reader));
76
+ if (result.length === max) {
77
+ break;
78
+ }
79
+ }
80
+ catch (e) {
81
+ if (result.length < min) {
82
+ throw e;
83
+ }
84
+ else {
85
+ break;
86
+ }
87
+ }
88
+ if (reader.value.startsWith(separator, reader.position)) {
89
+ reader.position += separator.length;
90
+ }
91
+ else if (result.length < min) {
92
+ throw new ParseError([separator.charAt(0)]);
93
+ }
94
+ else {
95
+ break;
96
+ }
97
+ }
98
+ return result;
99
+ },
100
+ stringify(value) {
101
+ return value.map((item) => format.stringify(item)).join(separator);
102
+ },
103
+ }),
104
+ repeated: (format) => ({
105
+ parse(reader) {
106
+ const result = [];
107
+ while (true) {
108
+ try {
109
+ result.push(format.parse(reader));
110
+ }
111
+ catch (e) {
112
+ break;
113
+ }
114
+ }
115
+ return result;
116
+ },
117
+ stringify(value) {
118
+ return value.map((item) => format.stringify(item)).join("");
119
+ },
120
+ }),
121
+ sequence: (...args) => ({
122
+ parse(reader) {
123
+ const result = {};
124
+ for (const part of args) {
125
+ if ("name" in part) {
126
+ result[part.name] = part.format.parse(reader);
127
+ }
128
+ else {
129
+ void part.parse(reader);
130
+ }
131
+ }
132
+ return result;
133
+ },
134
+ stringify: (value) => {
135
+ let result = "";
136
+ for (const part of args) {
137
+ if ("name" in part) {
138
+ result += part.format.stringify(value[part.name]);
139
+ }
140
+ }
141
+ return result;
142
+ },
143
+ }),
144
+ map: (format, map, reverse) => ({
145
+ parse(reader) {
146
+ return map(format.parse(reader));
147
+ },
148
+ stringify(value) {
149
+ return format.stringify(reverse(value));
150
+ },
151
+ }),
152
+ };
153
+ //# sourceMappingURL=string-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string-format.js","sourceRoot":"","sources":["../src/string-format.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yume-chan/android-bin",
3
- "version": "0.0.19",
3
+ "version": "0.0.21",
4
4
  "description": "Wrappers for Android built-in executables.",
5
5
  "keywords": [
6
6
  "adb",
@@ -25,21 +25,26 @@
25
25
  "main": "esm/index.js",
26
26
  "types": "esm/index.d.ts",
27
27
  "dependencies": {
28
- "@yume-chan/adb": "^0.0.19",
29
- "@yume-chan/stream-extra": "^0.0.19",
30
- "@yume-chan/struct": "^0.0.19",
31
- "tslib": "^2.4.1"
28
+ "@yume-chan/adb": "^0.0.21",
29
+ "@yume-chan/stream-extra": "^0.0.21",
30
+ "@yume-chan/struct": "^0.0.21",
31
+ "tslib": "^2.6.0"
32
32
  },
33
33
  "devDependencies": {
34
+ "@jest/globals": "^29.6.1",
34
35
  "@yume-chan/eslint-config": "^1.0.0",
35
36
  "@yume-chan/tsconfig": "^1.0.0",
36
- "eslint": "^8.36.0",
37
- "prettier": "^2.8.4",
38
- "typescript": "^4.9.4"
37
+ "cross-env": "^7.0.3",
38
+ "eslint": "^8.44.0",
39
+ "jest": "^29.5.0",
40
+ "prettier": "^3.0.0",
41
+ "ts-jest": "^29.1.1",
42
+ "typescript": "^5.1.6"
39
43
  },
40
44
  "scripts": {
41
45
  "build": "tsc -b tsconfig.build.json",
42
46
  "build:watch": "tsc -b tsconfig.build.json",
47
+ "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage",
43
48
  "lint": "eslint src/**/*.ts --fix && prettier src/**/*.ts --write --tab-width 4"
44
49
  }
45
50
  }
package/src/bu.ts CHANGED
@@ -1,26 +1,80 @@
1
- // cspell: ignore apks
2
- // cspell: ignore obbs
3
-
4
1
  import { AdbCommandBase } from "@yume-chan/adb";
2
+ import type { Consumable, ReadableStream } from "@yume-chan/stream-extra";
3
+ import { ConcatStringStream, DecodeUtf8Stream } from "@yume-chan/stream-extra";
5
4
 
6
5
  export interface AdbBackupOptions {
7
- apps: string[] | "all" | "all-including-system";
8
- apks: boolean;
9
- obbs: boolean;
10
- shared: boolean;
11
- widgets: boolean;
6
+ user: number;
7
+ saveSharedStorage?: boolean;
8
+ saveWidgets?: boolean;
9
+ packages: string[] | "user" | "all";
10
+ savePackageApk: boolean;
11
+ savePackageObb: boolean;
12
+ savePackageKeyValue: boolean;
12
13
  compress: boolean;
14
+ }
15
+
16
+ export interface AdbRestoreOptions {
13
17
  user: number;
18
+ file: ReadableStream<Consumable<Uint8Array>>;
14
19
  }
15
20
 
16
21
  export class AdbBackup extends AdbCommandBase {
17
- backup(options: AdbBackupOptions): Promise<void> {
18
- void options;
19
- throw new Error("Not implemented");
22
+ /**
23
+ * User must confirm backup on device within 60 seconds.
24
+ */
25
+ async backup(
26
+ options: AdbBackupOptions,
27
+ ): Promise<ReadableStream<Uint8Array>> {
28
+ const args = ["bu", "backup"];
29
+
30
+ if (options.user !== undefined) {
31
+ args.push("--user", options.user.toString());
32
+ }
33
+
34
+ args.push(options.saveSharedStorage ? "--shared" : "--no-shared");
35
+ args.push(options.saveWidgets ? "--widgets" : "--no-widgets");
36
+
37
+ args.push(options.savePackageApk ? "--apk" : "--no-apk");
38
+ args.push(options.savePackageObb ? "--obb" : "--no-obb");
39
+ args.push(
40
+ options.savePackageKeyValue ? "--key-value" : "--no-key-value",
41
+ );
42
+
43
+ args.push(options.compress ? "--compress" : "--no-compress");
44
+
45
+ if (typeof options.packages === "string") {
46
+ switch (options.packages) {
47
+ case "user":
48
+ args.push("--all", "--no-system");
49
+ break;
50
+ case "all":
51
+ args.push("--all", "--system");
52
+ break;
53
+ }
54
+ } else {
55
+ args.push(...options.packages);
56
+ }
57
+
58
+ const process = await this.adb.subprocess.spawn(args);
59
+ return process.stdout;
20
60
  }
21
61
 
22
- restore(options: AdbBackupOptions): Promise<void> {
23
- void options;
24
- throw new Error("Not implemented");
62
+ /**
63
+ * User must enter the password (if any) and
64
+ * confirm restore on device within 60 seconds.
65
+ */
66
+ async restore(options: AdbRestoreOptions): Promise<string> {
67
+ const args = ["bu", "restore"];
68
+ if (options.user !== undefined) {
69
+ args.push("--user", options.user.toString());
70
+ }
71
+ const process = await this.adb.subprocess.spawn(args);
72
+ const [output] = await Promise.all([
73
+ process.stdout
74
+ .pipeThrough(new DecodeUtf8Stream())
75
+ .pipeThrough(new ConcatStringStream()),
76
+ options.file.pipeTo(process.stdin),
77
+ ]);
78
+ return output;
25
79
  }
26
80
  }