serve-emul 0.0.4

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 (42) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/LICENSE +201 -0
  3. package/README.md +196 -0
  4. package/dist/ui/assets/index-Cm5-Tjhs.css +1 -0
  5. package/dist/ui/assets/index-CyUIa9dV.js +42 -0
  6. package/dist/ui/index.html +13 -0
  7. package/package.json +67 -0
  8. package/scripts/fetch-scrcpy.ts +28 -0
  9. package/scripts/release.ts +136 -0
  10. package/src/accessibility.ts +88 -0
  11. package/src/adb.ts +209 -0
  12. package/src/app-info.ts +114 -0
  13. package/src/app-management.ts +150 -0
  14. package/src/cli.ts +149 -0
  15. package/src/emulator.ts +229 -0
  16. package/src/input.ts +258 -0
  17. package/src/location.ts +135 -0
  18. package/src/route-playback.ts +359 -0
  19. package/src/scrcpy.ts +466 -0
  20. package/src/server.ts +1260 -0
  21. package/src/session-recorder.ts +149 -0
  22. package/src/ui/app.tsx +111 -0
  23. package/src/ui/components/accessibility-panel.tsx +113 -0
  24. package/src/ui/components/app-management-panel.tsx +256 -0
  25. package/src/ui/components/control-bar.tsx +24 -0
  26. package/src/ui/components/device-panel.tsx +532 -0
  27. package/src/ui/components/device-stream.tsx +142 -0
  28. package/src/ui/components/location-panel.tsx +584 -0
  29. package/src/ui/components/logcat-panel.tsx +100 -0
  30. package/src/ui/components/session-panel.tsx +127 -0
  31. package/src/ui/components/status-bar.tsx +19 -0
  32. package/src/ui/index.html +12 -0
  33. package/src/ui/lib/h264.ts +35 -0
  34. package/src/ui/lib/use-stream.ts +368 -0
  35. package/src/ui/main.tsx +7 -0
  36. package/src/ui/styles.css +708 -0
  37. package/src/ui/tsconfig.json +17 -0
  38. package/src/update-check.ts +93 -0
  39. package/vendor/scrcpy-server-v2.7 +0 -0
  40. package/vendor/scrcpy-server-v3.1 +0 -0
  41. package/vendor/scrcpy-server-v3.3.4 +0 -0
  42. package/vendor/scrcpy-server-v4.0 +0 -0
@@ -0,0 +1,93 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+
5
+ export const UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
6
+ export const UPDATE_CHECK_CACHE = join(homedir(), ".cache", "serve-emul", "update-check.json");
7
+
8
+ export type UpdateCache = {
9
+ checkedAt?: number;
10
+ latestVersion?: string;
11
+ };
12
+
13
+ export type UpdateCheckOptions = {
14
+ packageName: string;
15
+ currentVersion: string;
16
+ cachePath?: string;
17
+ now?: () => number;
18
+ fetchLatest?: (packageName: string) => Promise<string | null>;
19
+ readCache?: (cachePath: string) => Promise<UpdateCache | null>;
20
+ writeCache?: (cachePath: string, cache: UpdateCache) => Promise<void>;
21
+ };
22
+
23
+ function parseVersion(version: string): number[] {
24
+ return version
25
+ .replace(/^v/, "")
26
+ .split("-")[0]
27
+ .split(".")
28
+ .map((part) => Number(part))
29
+ .map((part) => (Number.isFinite(part) ? part : 0));
30
+ }
31
+
32
+ export function isNewerVersion(latest: string, current: string): boolean {
33
+ const latestParts = parseVersion(latest);
34
+ const currentParts = parseVersion(current);
35
+ const length = Math.max(latestParts.length, currentParts.length);
36
+
37
+ for (let i = 0; i < length; i++) {
38
+ const latestPart = latestParts[i] ?? 0;
39
+ const currentPart = currentParts[i] ?? 0;
40
+ if (latestPart > currentPart) return true;
41
+ if (latestPart < currentPart) return false;
42
+ }
43
+
44
+ return false;
45
+ }
46
+
47
+ export async function readUpdateCache(cachePath = UPDATE_CHECK_CACHE): Promise<UpdateCache | null> {
48
+ try {
49
+ return JSON.parse(await readFile(cachePath, "utf8")) as UpdateCache;
50
+ } catch {
51
+ return null;
52
+ }
53
+ }
54
+
55
+ export async function writeUpdateCache(cachePath: string, cache: UpdateCache) {
56
+ await mkdir(dirname(cachePath), { recursive: true });
57
+ await writeFile(cachePath, `${JSON.stringify(cache)}\n`);
58
+ }
59
+
60
+ export async function fetchLatestVersion(packageName: string): Promise<string | null> {
61
+ const res = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {
62
+ signal: AbortSignal.timeout(1500),
63
+ });
64
+ if (!res.ok) return null;
65
+
66
+ const latest = (await res.json()) as { version?: unknown };
67
+ return typeof latest.version === "string" ? latest.version : null;
68
+ }
69
+
70
+ export async function getUpdateNotice(options: UpdateCheckOptions): Promise<string | null> {
71
+ const cachePath = options.cachePath ?? UPDATE_CHECK_CACHE;
72
+ const now = options.now ?? Date.now;
73
+ const readCacheFn = options.readCache ?? readUpdateCache;
74
+ const writeCacheFn = options.writeCache ?? writeUpdateCache;
75
+ const fetchLatestFn = options.fetchLatest ?? fetchLatestVersion;
76
+
77
+ const cached = await readCacheFn(cachePath);
78
+ let latestVersion = cached?.latestVersion;
79
+
80
+ if (!cached?.checkedAt || !latestVersion || now() - cached.checkedAt >= UPDATE_CHECK_INTERVAL_MS) {
81
+ const fetchedVersion = await fetchLatestFn(options.packageName);
82
+ if (!fetchedVersion) return null;
83
+ latestVersion = fetchedVersion;
84
+ await writeCacheFn(cachePath, { checkedAt: now(), latestVersion });
85
+ }
86
+
87
+ if (!isNewerVersion(latestVersion, options.currentVersion)) return null;
88
+
89
+ return (
90
+ `Update available: ${options.packageName} ${options.currentVersion} -> ${latestVersion}\n` +
91
+ `Run: bunx ${options.packageName}@latest`
92
+ );
93
+ }
Binary file
Binary file
Binary file
Binary file