appduct 0.14.0 → 0.15.1
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/README.md +60 -287
- package/dist/artifact-inspect.d.ts +38 -39
- package/dist/bin.js +45 -3
- package/dist/cli/result-types.d.ts +27 -1
- package/dist/cli/routes/daemon/index.js +32 -1
- package/dist/cli/routes/daemon/run.js +963 -521
- package/dist/cli/routes/daemon/start.js +40 -1
- package/dist/cli/routes/daemon/status.js +41 -1
- package/dist/cli/routes/daemon/stop.js +40 -1
- package/dist/cli/routes/doctor.js +40 -2
- package/dist/cli/routes/events/index.js +32 -1
- package/dist/cli/routes/events/ls.js +40 -1
- package/dist/cli/routes/events/since.js +40 -1
- package/dist/cli/routes/events/tail.js +40 -1
- package/dist/cli/routes/init.js +207 -107
- package/dist/cli/routes/keygen.js +32 -1
- package/dist/cli/routes/mcp.js +135 -24
- package/dist/cli/routes/sessions/index.js +32 -1
- package/dist/cli/routes/sessions/link.js +141 -21
- package/dist/cli/routes/sessions/ls.js +40 -1
- package/dist/cli/routes/sessions/revoke.js +40 -1
- package/dist/cli/routes/tools/call.js +40 -1
- package/dist/cli/routes/tools/describe.js +40 -1
- package/dist/cli/routes/tools/index.js +32 -1
- package/dist/cli/routes/tools/ls.js +40 -1
- package/dist/client/attach-page.d.ts +39 -0
- package/dist/client/bootstrap.d.ts +17 -3
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.js +287 -112
- package/dist/commands/doctor.d.ts +3 -4
- package/dist/commands/init.d.ts +8 -2
- package/dist/commands/link.d.ts +10 -1
- package/dist/daemon/calls.d.ts +1 -1
- package/dist/daemon/config.d.ts +6 -0
- package/dist/daemon/daemon.d.ts +6 -1
- package/dist/daemon/links.d.ts +9 -5
- package/dist/daemon/listener.d.ts +28 -1
- package/dist/daemon/rpc-errors.d.ts +3 -0
- package/dist/daemon/sessions.d.ts +11 -7
- package/dist/daemon/tls.d.ts +0 -3
- package/dist/devtools-relay/attach-tab.d.ts +33 -0
- package/dist/devtools-relay/index.d.ts +8 -0
- package/dist/devtools-relay/memory-daemon-sockets.d.ts +20 -0
- package/dist/devtools-relay/memory-devtools-browser.d.ts +10 -0
- package/dist/devtools-relay/memory-page-channel.d.ts +16 -0
- package/dist/devtools-relay/node-daemon-socket.d.ts +3 -0
- package/dist/devtools-relay/node-devtools-browser.d.ts +3 -0
- package/dist/devtools-relay/ports.d.ts +48 -0
- package/dist/devtools-relay/relay.d.ts +16 -0
- package/dist/index.js +45 -3
- package/dist/link.d.ts +35 -1
- package/dist/mcp/connect-tool.d.ts +15 -2
- package/dist/native-scheme.d.ts +11 -7
- package/dist/scheme.d.ts +5 -1
- package/package.json +15 -5
package/dist/bin.js
CHANGED
|
@@ -128,8 +128,11 @@ var createCli = () => {
|
|
|
128
128
|
`link: deep-link URI scheme (also: APPDUCT_SCHEME; default: .appduct/config.json, then app.json's "expo.scheme", then the Android/iOS project files in <cwd>).`
|
|
129
129
|
).option(
|
|
130
130
|
"--open <target>",
|
|
131
|
-
"link: deliver the link automatically via adb/simctl/devicectl (android|ios-sim|ios-device; ios-device is experimental)."
|
|
132
|
-
).option(
|
|
131
|
+
"link: deliver the link automatically via adb/simctl/devicectl (android|ios-sim|ios-device; ios-device is experimental), or with `web <url>` return the page URL and a connect script for a web page."
|
|
132
|
+
).option(
|
|
133
|
+
"--browser-url <url>",
|
|
134
|
+
"link: with --open web, attach the tab of a Chrome launched with --remote-debugging-port (such as http://127.0.0.1:9222) and claim a session on it."
|
|
135
|
+
).option("--target-id <id>", "link: with --browser-url, the CDP target id of the tab to attach when several tabs match <url>.").option("--device <id>", "link: adb serial, simulator udid or paired-device udid to target when --open is ambiguous.").option(
|
|
133
136
|
"--app-id <id>",
|
|
134
137
|
`link: installed app id for --open android/ios-device (default: .appduct/config.json's "appId.<platform>").`
|
|
135
138
|
).option(
|
|
@@ -171,6 +174,7 @@ var KNOWN_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
|
171
174
|
"daemonLogMaxBytes",
|
|
172
175
|
"eventsLogMaxBytes",
|
|
173
176
|
"policy",
|
|
177
|
+
"webOrigins",
|
|
174
178
|
"advertisedIp",
|
|
175
179
|
"scheme",
|
|
176
180
|
"restartDaemonOnVersionMismatch"
|
|
@@ -231,6 +235,7 @@ var defaultConfig = (paths) => {
|
|
|
231
235
|
daemonLogMaxBytes: DEFAULT_DAEMON_LOG_MAX_BYTES,
|
|
232
236
|
eventsLogMaxBytes: 10 * 1024 * 1024,
|
|
233
237
|
restartDaemonOnVersionMismatch: false,
|
|
238
|
+
webOrigins: [],
|
|
234
239
|
policy: {
|
|
235
240
|
default: "allow",
|
|
236
241
|
destructive: "allow"
|
|
@@ -301,6 +306,12 @@ var loadConfig = async (paths, options = {}) => {
|
|
|
301
306
|
"restartDaemonOnVersionMismatch"
|
|
302
307
|
);
|
|
303
308
|
}
|
|
309
|
+
if (parsed.webOrigins !== void 0) {
|
|
310
|
+
if (!Array.isArray(parsed.webOrigins)) {
|
|
311
|
+
throw configError("webOrigins", "must be an array of origin strings.");
|
|
312
|
+
}
|
|
313
|
+
config.webOrigins = parsed.webOrigins.map((origin) => requireNonEmptyString(origin, "webOrigins"));
|
|
314
|
+
}
|
|
304
315
|
if (parsed.policy !== void 0) {
|
|
305
316
|
if (typeof parsed.policy !== "object" || parsed.policy === null || Array.isArray(parsed.policy)) {
|
|
306
317
|
throw configError("policy", "must be an object.");
|
|
@@ -409,7 +420,7 @@ var EXIT_CODE_BY_ERROR_TYPE = {
|
|
|
409
420
|
// EX_NOINPUT (66): "an input file did not exist or was not readable" — `doctor` throws this for a
|
|
410
421
|
// missing external tool or an unreadable/corrupt artifact, deliberately distinct from every other
|
|
411
422
|
// code here so a release pipeline can't mistake "we couldn't tell" for either a clean pass or an
|
|
412
|
-
// assertion failure
|
|
423
|
+
// assertion failure.
|
|
413
424
|
inspection_error: 66,
|
|
414
425
|
connection_error: 70,
|
|
415
426
|
session_error: 71,
|
|
@@ -860,6 +871,36 @@ var renderInvokeData = (colors, data, flags) => {
|
|
|
860
871
|
return [colors.green("Result"), formatScalar(data, flags)];
|
|
861
872
|
};
|
|
862
873
|
var renderLinkData = (colors, data, flags, qr) => {
|
|
874
|
+
if ("attached" in data) {
|
|
875
|
+
return [
|
|
876
|
+
colors.green("Page Attached"),
|
|
877
|
+
...renderFields(
|
|
878
|
+
"Page",
|
|
879
|
+
[
|
|
880
|
+
["Session", data.sessionId],
|
|
881
|
+
["Tab", data.targetId],
|
|
882
|
+
["URL", data.url],
|
|
883
|
+
["Expires", new Date(data.expiresAt * 1e3).toISOString()]
|
|
884
|
+
],
|
|
885
|
+
flags
|
|
886
|
+
)
|
|
887
|
+
];
|
|
888
|
+
}
|
|
889
|
+
if ("script" in data) {
|
|
890
|
+
return [
|
|
891
|
+
colors.green("Link Created"),
|
|
892
|
+
...renderFields(
|
|
893
|
+
"Link",
|
|
894
|
+
[
|
|
895
|
+
["Session", data.sessionId],
|
|
896
|
+
["URL", data.url],
|
|
897
|
+
["Script", data.script],
|
|
898
|
+
["Expires", new Date(data.expiresAt * 1e3).toISOString()]
|
|
899
|
+
],
|
|
900
|
+
flags
|
|
901
|
+
)
|
|
902
|
+
];
|
|
903
|
+
}
|
|
863
904
|
const lines = [
|
|
864
905
|
colors.green("Link Created"),
|
|
865
906
|
...renderFields(
|
|
@@ -980,6 +1021,7 @@ var renderDaemonStatusData = (colors, data, flags) => {
|
|
|
980
1021
|
["PID", data.daemon.pid],
|
|
981
1022
|
["Started at", data.daemon.started_at],
|
|
982
1023
|
["WSS port", data.daemon.wss_port],
|
|
1024
|
+
["Web port", data.daemon.web_port],
|
|
983
1025
|
["Pinned keys", data.daemon.pinned_keys.length],
|
|
984
1026
|
["Sessions", data.daemon.session_count]
|
|
985
1027
|
],
|
|
@@ -66,6 +66,11 @@ export type InitCommandData = {
|
|
|
66
66
|
* tier rather than `"--scheme"`/`"already-recorded"` — `init`'s human-readable hint surfaces
|
|
67
67
|
* this so a native-probe result says which file to go edit, not just which platform. */
|
|
68
68
|
origin?: string;
|
|
69
|
+
/** The native platforms discovery saw in this project (`"android"` for a Gradle file or Android
|
|
70
|
+
* manifest, `"ios"` for an `Info.plist` or `project.yml`), alphabetical. Unlike `source`, which
|
|
71
|
+
* names the one input that won, this lists every platform, and it is reported on every run,
|
|
72
|
+
* including `"already-recorded"` and `"--scheme"`. Omitted when none was seen. */
|
|
73
|
+
platforms?: ("android" | "ios")[];
|
|
69
74
|
/** The project config did not exist before this run. */
|
|
70
75
|
created: boolean;
|
|
71
76
|
/** This run wrote to the file. `false` on an idempotent re-run. */
|
|
@@ -111,6 +116,26 @@ export type LinkCommandData = {
|
|
|
111
116
|
/** The `--open` target the link was delivered to, alongside `delivered`. */
|
|
112
117
|
target?: OpenTarget;
|
|
113
118
|
};
|
|
119
|
+
/** `appduct sessions link --open web <url>`: the page URL carrying the link, and the script that
|
|
120
|
+
* connects an already-open page instead. */
|
|
121
|
+
export type WebLinkCommandData = {
|
|
122
|
+
sessionId: string;
|
|
123
|
+
url: string;
|
|
124
|
+
script: string;
|
|
125
|
+
/** Unix seconds. */
|
|
126
|
+
expiresAt: number;
|
|
127
|
+
};
|
|
128
|
+
/** `appduct sessions link --open web <url> --browser-url <u>`: the tab the daemon attached and the
|
|
129
|
+
* session it will claim. */
|
|
130
|
+
export type WebAttachCommandData = {
|
|
131
|
+
attached: true;
|
|
132
|
+
sessionId: string;
|
|
133
|
+
url: string;
|
|
134
|
+
/** The CDP target id of the attached tab. */
|
|
135
|
+
targetId: string;
|
|
136
|
+
/** Unix seconds. */
|
|
137
|
+
expiresAt: number;
|
|
138
|
+
};
|
|
114
139
|
/** `appduct sessions ls`: `sessions.list` passthrough, verbatim (ARCHITECTURE.md §10: "--json
|
|
115
140
|
* passthrough"). */
|
|
116
141
|
export type LsCommandData = SessionSummary[];
|
|
@@ -171,7 +196,7 @@ export type DaemonStopCommandData = {
|
|
|
171
196
|
method: "rpc" | "sigterm";
|
|
172
197
|
};
|
|
173
198
|
};
|
|
174
|
-
/** `appduct doctor <artifact>`: artifact-level Appduct inclusion report
|
|
199
|
+
/** `appduct doctor <artifact>`: artifact-level Appduct inclusion report. */
|
|
175
200
|
export type DoctorCommandData = {
|
|
176
201
|
artifact: string;
|
|
177
202
|
platform: "ios" | "android";
|
|
@@ -194,6 +219,7 @@ export type DaemonStatusCommandData = {
|
|
|
194
219
|
pid: number;
|
|
195
220
|
started_at: string;
|
|
196
221
|
wss_port: number;
|
|
222
|
+
web_port: number;
|
|
197
223
|
pinned_keys: string[];
|
|
198
224
|
session_count: number;
|
|
199
225
|
};
|
|
@@ -93,7 +93,7 @@ var EXIT_CODE_BY_ERROR_TYPE = {
|
|
|
93
93
|
// EX_NOINPUT (66): "an input file did not exist or was not readable" — `doctor` throws this for a
|
|
94
94
|
// missing external tool or an unreadable/corrupt artifact, deliberately distinct from every other
|
|
95
95
|
// code here so a release pipeline can't mistake "we couldn't tell" for either a clean pass or an
|
|
96
|
-
// assertion failure
|
|
96
|
+
// assertion failure.
|
|
97
97
|
inspection_error: 66,
|
|
98
98
|
connection_error: 70,
|
|
99
99
|
session_error: 71,
|
|
@@ -549,6 +549,36 @@ var renderInvokeData = (colors, data, flags) => {
|
|
|
549
549
|
return [colors.green("Result"), formatScalar(data, flags)];
|
|
550
550
|
};
|
|
551
551
|
var renderLinkData = (colors, data, flags, qr) => {
|
|
552
|
+
if ("attached" in data) {
|
|
553
|
+
return [
|
|
554
|
+
colors.green("Page Attached"),
|
|
555
|
+
...renderFields(
|
|
556
|
+
"Page",
|
|
557
|
+
[
|
|
558
|
+
["Session", data.sessionId],
|
|
559
|
+
["Tab", data.targetId],
|
|
560
|
+
["URL", data.url],
|
|
561
|
+
["Expires", new Date(data.expiresAt * 1e3).toISOString()]
|
|
562
|
+
],
|
|
563
|
+
flags
|
|
564
|
+
)
|
|
565
|
+
];
|
|
566
|
+
}
|
|
567
|
+
if ("script" in data) {
|
|
568
|
+
return [
|
|
569
|
+
colors.green("Link Created"),
|
|
570
|
+
...renderFields(
|
|
571
|
+
"Link",
|
|
572
|
+
[
|
|
573
|
+
["Session", data.sessionId],
|
|
574
|
+
["URL", data.url],
|
|
575
|
+
["Script", data.script],
|
|
576
|
+
["Expires", new Date(data.expiresAt * 1e3).toISOString()]
|
|
577
|
+
],
|
|
578
|
+
flags
|
|
579
|
+
)
|
|
580
|
+
];
|
|
581
|
+
}
|
|
552
582
|
const lines = [
|
|
553
583
|
colors.green("Link Created"),
|
|
554
584
|
...renderFields(
|
|
@@ -669,6 +699,7 @@ var renderDaemonStatusData = (colors, data, flags) => {
|
|
|
669
699
|
["PID", data.daemon.pid],
|
|
670
700
|
["Started at", data.daemon.started_at],
|
|
671
701
|
["WSS port", data.daemon.wss_port],
|
|
702
|
+
["Web port", data.daemon.web_port],
|
|
672
703
|
["Pinned keys", data.daemon.pinned_keys.length],
|
|
673
704
|
["Sessions", data.daemon.session_count]
|
|
674
705
|
],
|