adjacent-dev-client 0.1.0

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.
package/dist/checks.js ADDED
@@ -0,0 +1,119 @@
1
+ import { PwaValidator } from "@bubblewrap/validator";
2
+ import { failed, passed } from "adjacent-cli";
3
+ import { inspectAndroidToolchain } from "./android-wrapper.js";
4
+ /**
5
+ * Reads a digital asset links document the way Android does, and says what is
6
+ * wrong with it.
7
+ *
8
+ * A wrong or unreachable one is the single most common Android fault: the app
9
+ * launches with a browser address bar across the top, or does not launch at
10
+ * all, and nothing anywhere says why. Every rule here is one that produces
11
+ * exactly that symptom.
12
+ */
13
+ export function describeAssetLinksProblem(requested, response, body) {
14
+ const landed = new URL(response.url);
15
+ // Android does not follow a redirect to another origin. It concludes the
16
+ // links are absent, which looks identical to never having written them.
17
+ if (landed.origin !== requested.origin) {
18
+ return {
19
+ detail: `${requested.origin} redirects to ${landed.origin}.`,
20
+ remedy: "Package the app for the origin you redirect to, canonical www or bare, " +
21
+ "because Android reads the asset links of the origin it was given and follows no redirect across origins.",
22
+ };
23
+ }
24
+ if (!response.ok) {
25
+ return {
26
+ detail: `${requested.href} answered ${response.status}.`,
27
+ remedy: "It has to be served from the root of the domain, not from the app's own path: " +
28
+ "an app at example.com/player still needs example.com/.well-known/assetlinks.json.",
29
+ };
30
+ }
31
+ let parsed;
32
+ try {
33
+ parsed = JSON.parse(body);
34
+ }
35
+ catch {
36
+ return {
37
+ detail: "The document is not valid JSON.",
38
+ remedy: "A fingerprint pasted in without a comma between it and the last one is the usual cause.",
39
+ };
40
+ }
41
+ if (!Array.isArray(parsed) || parsed.length === 0) {
42
+ return { detail: "The document is not a non-empty array of statements.", remedy: "" };
43
+ }
44
+ const targets = parsed.map((statement) => statement.target);
45
+ if (targets.some((target) => typeof target?.package_name !== "string")) {
46
+ return { detail: "A statement has no target package_name.", remedy: "" };
47
+ }
48
+ const fingerprints = targets.flatMap((target) => Array.isArray(target?.sha256_cert_fingerprints) ? target.sha256_cert_fingerprints : []);
49
+ if (fingerprints.length === 0) {
50
+ return { detail: "No sha256_cert_fingerprints are listed.", remedy: "" };
51
+ }
52
+ // Play re-signs an uploaded bundle, so the fingerprint that shipped is not
53
+ // the one serving the store's installs.
54
+ if (fingerprints.length === 1) {
55
+ return {
56
+ detail: "Only one fingerprint is listed.",
57
+ remedy: "Google Play re-signs what you upload, so a store build needs Play's own " +
58
+ "SHA-256 from App integrity beside the one you signed with.",
59
+ };
60
+ }
61
+ return undefined;
62
+ }
63
+ const assetLinks = {
64
+ description: "Digital asset links are served from the root of the domain",
65
+ async run({ url }) {
66
+ if (url === undefined)
67
+ return passed;
68
+ const requested = new URL("/.well-known/assetlinks.json", url);
69
+ const response = await fetch(requested, { redirect: "follow" }).catch(() => undefined);
70
+ if (!response) {
71
+ return failed([`${requested.href} could not be reached.`], "Android reads it from there and nowhere else, and shows a browser address bar when it cannot.");
72
+ }
73
+ const problem = describeAssetLinksProblem(requested, response, await response.text().catch(() => ""));
74
+ if (!problem)
75
+ return passed;
76
+ return failed([problem.detail], problem.remedy ||
77
+ "Android shows a browser address bar over the app when the asset links do not match it.");
78
+ },
79
+ };
80
+ const toolchain = {
81
+ description: "The Android toolchain is usable",
82
+ async run() {
83
+ try {
84
+ const found = await inspectAndroidToolchain();
85
+ return found.licensesAccepted
86
+ ? passed
87
+ : failed(["The Android SDK licences have not been accepted."], "Run: sdkmanager --licences");
88
+ }
89
+ catch (error) {
90
+ return failed([error instanceof Error ? error.message : String(error)], "The Android command line tools need exactly JDK 17 and an Android SDK.");
91
+ }
92
+ },
93
+ };
94
+ /**
95
+ * A PageSpeed Insights run, so it needs a reachable production build and takes
96
+ * far too long to sit in the development loop. It only runs when a URL is given.
97
+ */
98
+ const qualityCriteria = {
99
+ description: "The deployed app meets the Trusted Web Activity criteria",
100
+ async run({ url }) {
101
+ if (url === undefined)
102
+ return passed;
103
+ const result = await PwaValidator.validate(new URL(url));
104
+ return result.status === "PASS"
105
+ ? passed
106
+ : failed([
107
+ `Progressive Web App: ${result.scores.pwa.printValue}`,
108
+ `Performance: ${result.scores.performance.printValue}`,
109
+ `Accessibility: ${result.scores.accessibility.printValue}`,
110
+ `Report: ${result.psiWebUrl}`,
111
+ ], "An app that fails these launches in a Custom Tab with a visible URL bar, not fullscreen.");
112
+ },
113
+ };
114
+ export const ANDROID_CHECKS = [
115
+ toolchain,
116
+ assetLinks,
117
+ qualityCriteria,
118
+ ];
119
+ //# sourceMappingURL=checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.js","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { ANDROID_CHECKS, describeAssetLinksProblem, type AssetLinksProblem, } from "./checks.js";
2
+ export { runAndroidDev, runAndroidInstall } from "./android-dev.js";
3
+ export { describePackageIdProblem, inspectAndroidToolchain, type AndroidToolchain, } from "./android-wrapper.js";
4
+ export { parseAdbDevices, selectAndroidDevice, type AndroidDevice, } from "./android.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,KAAK,gBAAgB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { ANDROID_CHECKS, describeAssetLinksProblem, } from "./checks.js";
2
+ export { runAndroidDev, runAndroidInstall } from "./android-dev.js";
3
+ export { describePackageIdProblem, inspectAndroidToolchain, } from "./android-wrapper.js";
4
+ export { parseAdbDevices, selectAndroidDevice, } from "./android.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,yBAAyB,GAE1B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EACL,wBAAwB,EACxB,uBAAuB,GAExB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,eAAe,EACf,mBAAmB,GAEpB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ import type { AndroidAssetLink } from "./android-wrapper.js";
3
+ export interface AdjacentTunnel {
4
+ readonly assetLinksUrl: string;
5
+ readonly origin: string;
6
+ readonly process: ChildProcess;
7
+ readonly setAssetLink: (assetLink: AndroidAssetLink) => void;
8
+ readonly stop: () => Promise<void>;
9
+ }
10
+ export declare function startAdjacentTunnel(projectRoot: string, port: number, verbose?: boolean): Promise<AdjacentTunnel>;
11
+ //# sourceMappingURL=tunnel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["../src/tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAI9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAK7D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,YAAY,EAAE,CAAC,SAAS,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC;AAsBD,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,UAAQ,GACd,OAAO,CAAC,cAAc,CAAC,CAmEzB"}
package/dist/tunnel.js ADDED
@@ -0,0 +1,90 @@
1
+ import { spawn } from "node:child_process";
2
+ import { createServer } from "node:http";
3
+ const ADJACENT_DEV_HOSTNAME = "adj.digitospace.com";
4
+ const ADJACENT_TUNNEL = "adjacent-dev";
5
+ function listen(server) {
6
+ return new Promise((resolve, reject) => {
7
+ server.once("error", reject);
8
+ server.listen(0, "127.0.0.1", () => {
9
+ const address = server.address();
10
+ if (!address || typeof address === "string") {
11
+ reject(new Error("Could not allocate the Digital Asset Links server."));
12
+ return;
13
+ }
14
+ resolve(address.port);
15
+ });
16
+ });
17
+ }
18
+ function close(server) {
19
+ return new Promise((resolve, reject) => {
20
+ server.close((error) => error ? reject(error) : resolve());
21
+ });
22
+ }
23
+ export async function startAdjacentTunnel(projectRoot, port, verbose = false) {
24
+ let assetLink;
25
+ const assetLinksServer = createServer((_request, response) => {
26
+ if (!assetLink) {
27
+ response.writeHead(503, { "content-type": "application/json" });
28
+ response.end(JSON.stringify({ error: "Android wrapper is still being prepared." }));
29
+ return;
30
+ }
31
+ response.writeHead(200, {
32
+ "cache-control": "no-store",
33
+ "content-type": "application/json",
34
+ });
35
+ response.end(JSON.stringify([{
36
+ relation: ["delegate_permission/common.handle_all_urls"],
37
+ target: {
38
+ namespace: "android_app",
39
+ package_name: assetLink.packageId,
40
+ sha256_cert_fingerprints: [assetLink.sha256Fingerprint],
41
+ },
42
+ }]));
43
+ });
44
+ const assetLinksPort = await listen(assetLinksServer);
45
+ const origin = `https://${ADJACENT_DEV_HOSTNAME}`;
46
+ const tunnelProcess = spawn("cloudflared", [
47
+ "tunnel",
48
+ "--no-autoupdate",
49
+ "--no-prechecks",
50
+ "--url",
51
+ `http://127.0.0.1:${port}`,
52
+ "run",
53
+ ADJACENT_TUNNEL,
54
+ ], {
55
+ cwd: projectRoot,
56
+ stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
57
+ });
58
+ if (!verbose) {
59
+ const recentOutput = [];
60
+ const capture = (chunk) => {
61
+ recentOutput.push(...chunk.toString().split("\n").filter(Boolean));
62
+ if (recentOutput.length > 20)
63
+ recentOutput.splice(0, recentOutput.length - 20);
64
+ };
65
+ tunnelProcess.stdout?.on("data", capture);
66
+ tunnelProcess.stderr?.on("data", capture);
67
+ tunnelProcess.once("exit", (code, signal) => {
68
+ if (code === 0 || signal === "SIGTERM")
69
+ return;
70
+ const details = recentOutput.length > 0 ? `\n${recentOutput.join("\n")}` : "";
71
+ console.error(`Adjacent tunnel exited with ${code ?? signal ?? "an unknown error"}.${details}`);
72
+ });
73
+ }
74
+ tunnelProcess.once("error", (error) => {
75
+ console.error(`Adjacent tunnel failed: ${error.message}`);
76
+ });
77
+ return {
78
+ assetLinksUrl: `http://127.0.0.1:${assetLinksPort}`,
79
+ origin,
80
+ process: tunnelProcess,
81
+ setAssetLink(nextAssetLink) {
82
+ assetLink = nextAssetLink;
83
+ },
84
+ async stop() {
85
+ tunnelProcess.kill("SIGTERM");
86
+ await close(assetLinksServer);
87
+ },
88
+ };
89
+ }
90
+ //# sourceMappingURL=tunnel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../src/tunnel.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "adjacent-dev-client",
3
+ "version": "0.1.0",
4
+ "description": "Runs an Adjacent app on a real Android device, over a trusted tunnel and inside a Trusted Web Activity.",
5
+ "keywords": [
6
+ "adjacent",
7
+ "android",
8
+ "twa",
9
+ "pwa",
10
+ "development"
11
+ ],
12
+ "license": "MIT",
13
+ "author": "Eric Kweyunga",
14
+ "homepage": "https://github.com/erickweyunga/adjacent-framework/blob/main/docs/android.md",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/erickweyunga/adjacent-framework.git",
18
+ "directory": "packages/adjacent-dev-client"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/erickweyunga/adjacent-framework/issues"
22
+ },
23
+ "type": "module",
24
+ "main": "./dist/index.js",
25
+ "types": "./dist/index.d.ts",
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "import": "./dist/index.js",
30
+ "default": "./dist/index.js"
31
+ },
32
+ "./package.json": "./package.json"
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "CHANGELOG.md",
38
+ "LICENSE"
39
+ ],
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "engines": {
44
+ "node": ">=20.12.0"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc -p tsconfig.build.json",
48
+ "prepublishOnly": "npm run build",
49
+ "test": "bun test",
50
+ "typecheck": "tsc --noEmit"
51
+ },
52
+ "dependencies": {
53
+ "@bubblewrap/core": "^1.25.0",
54
+ "@bubblewrap/validator": "^1.25.0",
55
+ "adjacent-cli": "workspace:~"
56
+ },
57
+ "devDependencies": {
58
+ "@types/bun": "^1.3.13",
59
+ "@types/node": "^20",
60
+ "typescript": "^5"
61
+ }
62
+ }