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.
Files changed (55) hide show
  1. package/README.md +60 -287
  2. package/dist/artifact-inspect.d.ts +38 -39
  3. package/dist/bin.js +45 -3
  4. package/dist/cli/result-types.d.ts +27 -1
  5. package/dist/cli/routes/daemon/index.js +32 -1
  6. package/dist/cli/routes/daemon/run.js +963 -521
  7. package/dist/cli/routes/daemon/start.js +40 -1
  8. package/dist/cli/routes/daemon/status.js +41 -1
  9. package/dist/cli/routes/daemon/stop.js +40 -1
  10. package/dist/cli/routes/doctor.js +40 -2
  11. package/dist/cli/routes/events/index.js +32 -1
  12. package/dist/cli/routes/events/ls.js +40 -1
  13. package/dist/cli/routes/events/since.js +40 -1
  14. package/dist/cli/routes/events/tail.js +40 -1
  15. package/dist/cli/routes/init.js +207 -107
  16. package/dist/cli/routes/keygen.js +32 -1
  17. package/dist/cli/routes/mcp.js +135 -24
  18. package/dist/cli/routes/sessions/index.js +32 -1
  19. package/dist/cli/routes/sessions/link.js +141 -21
  20. package/dist/cli/routes/sessions/ls.js +40 -1
  21. package/dist/cli/routes/sessions/revoke.js +40 -1
  22. package/dist/cli/routes/tools/call.js +40 -1
  23. package/dist/cli/routes/tools/describe.js +40 -1
  24. package/dist/cli/routes/tools/index.js +32 -1
  25. package/dist/cli/routes/tools/ls.js +40 -1
  26. package/dist/client/attach-page.d.ts +39 -0
  27. package/dist/client/bootstrap.d.ts +17 -3
  28. package/dist/client/index.d.ts +2 -1
  29. package/dist/client/index.js +287 -112
  30. package/dist/commands/doctor.d.ts +3 -4
  31. package/dist/commands/init.d.ts +8 -2
  32. package/dist/commands/link.d.ts +10 -1
  33. package/dist/daemon/calls.d.ts +1 -1
  34. package/dist/daemon/config.d.ts +6 -0
  35. package/dist/daemon/daemon.d.ts +6 -1
  36. package/dist/daemon/links.d.ts +9 -5
  37. package/dist/daemon/listener.d.ts +28 -1
  38. package/dist/daemon/rpc-errors.d.ts +3 -0
  39. package/dist/daemon/sessions.d.ts +11 -7
  40. package/dist/daemon/tls.d.ts +0 -3
  41. package/dist/devtools-relay/attach-tab.d.ts +33 -0
  42. package/dist/devtools-relay/index.d.ts +8 -0
  43. package/dist/devtools-relay/memory-daemon-sockets.d.ts +20 -0
  44. package/dist/devtools-relay/memory-devtools-browser.d.ts +10 -0
  45. package/dist/devtools-relay/memory-page-channel.d.ts +16 -0
  46. package/dist/devtools-relay/node-daemon-socket.d.ts +3 -0
  47. package/dist/devtools-relay/node-devtools-browser.d.ts +3 -0
  48. package/dist/devtools-relay/ports.d.ts +48 -0
  49. package/dist/devtools-relay/relay.d.ts +16 -0
  50. package/dist/index.js +45 -3
  51. package/dist/link.d.ts +35 -1
  52. package/dist/mcp/connect-tool.d.ts +15 -2
  53. package/dist/native-scheme.d.ts +11 -7
  54. package/dist/scheme.d.ts +5 -1
  55. 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("--device <id>", "link: adb serial, simulator udid or paired-device udid to target when --open is ambiguous.").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 (docs/tasks/08-appduct-doctor.md).
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 (docs/tasks/08). */
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 (docs/tasks/08-appduct-doctor.md).
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
  ],