lim 0.28.4 → 0.28.6

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 (32) hide show
  1. package/README.md +15 -0
  2. package/dist/commands/android/launch-app.d.ts +22 -0
  3. package/dist/commands/android/launch-app.d.ts.map +1 -0
  4. package/dist/commands/android/launch-app.js +79 -0
  5. package/dist/commands/android/launch-app.js.map +1 -0
  6. package/dist/commands/{ios/stop-microphone-playback.d.ts → android/terminate-app.d.ts} +5 -2
  7. package/dist/commands/android/terminate-app.d.ts.map +1 -0
  8. package/dist/commands/android/terminate-app.js +42 -0
  9. package/dist/commands/android/terminate-app.js.map +1 -0
  10. package/dist/commands/ios/attach-xcode.d.ts +20 -0
  11. package/dist/commands/ios/attach-xcode.d.ts.map +1 -0
  12. package/dist/commands/ios/attach-xcode.js +66 -0
  13. package/dist/commands/ios/attach-xcode.js.map +1 -0
  14. package/dist/commands/ios/{play-on-microphone.d.ts → microphone.d.ts} +4 -3
  15. package/dist/commands/ios/microphone.d.ts.map +1 -0
  16. package/dist/commands/ios/microphone.js +89 -0
  17. package/dist/commands/ios/microphone.js.map +1 -0
  18. package/dist/lib/format-app-exit.d.ts +8 -0
  19. package/dist/lib/format-app-exit.d.ts.map +1 -0
  20. package/dist/lib/format-app-exit.js +29 -0
  21. package/dist/lib/format-app-exit.js.map +1 -0
  22. package/dist/lib/format-app-exit.test.d.ts +2 -0
  23. package/dist/lib/format-app-exit.test.d.ts.map +1 -0
  24. package/dist/lib/format-app-exit.test.js +49 -0
  25. package/dist/lib/format-app-exit.test.js.map +1 -0
  26. package/package.json +3 -3
  27. package/dist/commands/ios/play-on-microphone.d.ts.map +0 -1
  28. package/dist/commands/ios/play-on-microphone.js +0 -69
  29. package/dist/commands/ios/play-on-microphone.js.map +0 -1
  30. package/dist/commands/ios/stop-microphone-playback.d.ts.map +0 -1
  31. package/dist/commands/ios/stop-microphone-playback.js +0 -41
  32. package/dist/commands/ios/stop-microphone-playback.js.map +0 -1
package/README.md CHANGED
@@ -137,6 +137,7 @@ lim ios create # Create a new iOS instance
137
137
  lim ios list # List all ready iOS instances
138
138
  lim ios get <ID> # Get details of a specific instance
139
139
  lim ios delete <ID> # Delete an instance
140
+ lim ios attach-xcode # Attach an Xcode target to the simulator
140
141
  lim ios info # Get device info from a running instance
141
142
  ```
142
143
 
@@ -255,6 +256,20 @@ lim ios delete-file Documents/photo.jpeg --bundle-id com.example.app --container
255
256
  lim ios lsof
256
257
  ```
257
258
 
259
+ #### Xcode Attachment
260
+
261
+ Attach an existing Xcode target so future simulator builds are installed automatically:
262
+
263
+ ```bash
264
+ # Attach the last used Xcode target to the last used iOS simulator
265
+ lim ios attach-xcode
266
+
267
+ # Select the Xcode target and simulator explicitly
268
+ lim ios attach-xcode sandbox_def456 --id ios_abc123
269
+ ```
270
+
271
+ This is the iOS-oriented equivalent of `lim xcode attach-simulator ios_abc123 --id sandbox_def456`.
272
+
258
273
  #### App Management (iOS only)
259
274
 
260
275
  ```bash
@@ -0,0 +1,22 @@
1
+ import { BaseCommand } from '../../base-command';
2
+ export default class AndroidLaunchApp extends BaseCommand {
3
+ static summary: string;
4
+ static description: string;
5
+ static examples: string[];
6
+ static args: {
7
+ packageName: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
8
+ };
9
+ static flags: {
10
+ id: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ detach: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
12
+ mode: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ 'api-key': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
15
+ quiet: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ create: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
17
+ workspace: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ daemon: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
19
+ };
20
+ run(): Promise<void>;
21
+ }
22
+ //# sourceMappingURL=launch-app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch-app.d.ts","sourceRoot":"","sources":["../../../src/commands/android/launch-app.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAIjD,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,WAAW;IACvD,MAAM,CAAC,OAAO,SAAiD;IAC/D,MAAM,CAAC,WAAW,SACyW;IAC3X,MAAM,CAAC,QAAQ,WAIb;IAEF,MAAM,CAAC,IAAI;;MAET;IAEF,MAAM,CAAC,KAAK;;;;;;;;;;MAeV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAmD3B"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../base-command");
5
+ const instance_client_factory_1 = require("../../lib/instance-client-factory");
6
+ const format_app_exit_1 = require("../../lib/format-app-exit");
7
+ class AndroidLaunchApp extends base_command_1.BaseCommand {
8
+ async run() {
9
+ const { args, flags } = await this.parse(AndroidLaunchApp);
10
+ this.setParsedFlags(flags);
11
+ await this.withAuth(async () => {
12
+ const resolvedInstance = this.resolveAndroidInstance(flags.id);
13
+ const mode = flags.mode;
14
+ // The appExit notification that ends this command is delivered on the
15
+ // launching client's signaling WebSocket, so both paths use a direct
16
+ // connection rather than a daemon session.
17
+ const { client, disconnect } = await (0, instance_client_factory_1.getAndroidInstanceClient)(this.client, resolvedInstance);
18
+ try {
19
+ if (flags.detach) {
20
+ await client.launchApp(args.packageName, { mode });
21
+ this.log(`Launched ${args.packageName}`);
22
+ return;
23
+ }
24
+ let notifyAppExited = () => { };
25
+ const appExited = new Promise((resolve) => {
26
+ notifyAppExited = resolve;
27
+ });
28
+ await client.launchApp(args.packageName, {
29
+ mode,
30
+ onExit: (logs, info) => {
31
+ this.log((0, format_app_exit_1.formatAppExit)(info, logs));
32
+ notifyAppExited();
33
+ },
34
+ });
35
+ this.logToStderr(`Launched ${args.packageName}. Watching until the app exits; press Ctrl+C to stop earlier, or pass --detach to skip watching.`);
36
+ await new Promise((resolve) => {
37
+ const keepAlive = setInterval(() => { }, 1 << 30);
38
+ const finish = () => {
39
+ clearInterval(keepAlive);
40
+ resolve();
41
+ };
42
+ process.on('SIGINT', finish);
43
+ process.on('SIGTERM', finish);
44
+ void appExited.then(finish);
45
+ });
46
+ }
47
+ finally {
48
+ disconnect();
49
+ }
50
+ });
51
+ }
52
+ }
53
+ AndroidLaunchApp.summary = 'Launch an app on a running Android instance';
54
+ AndroidLaunchApp.description = 'Launch an installed app on a running Android instance by package name and watch it until it exits: when the app crashes, ANRs, or stops, the exit reason, crash details, and a recent app log tail are printed. Use `--detach` to exit right after the launch instead. Choose `ForegroundIfRunning` to bring an already-running app to the front or `RelaunchIfRunning` to restart it.';
55
+ AndroidLaunchApp.examples = [
56
+ '<%= config.bin %> android launch-app com.example.app',
57
+ '<%= config.bin %> android launch-app com.example.app --detach',
58
+ '<%= config.bin %> android launch-app com.example.app --mode RelaunchIfRunning --id <instance-ID>',
59
+ ];
60
+ AndroidLaunchApp.args = {
61
+ packageName: core_1.Args.string({ description: 'Package name of the app to launch', required: true }),
62
+ };
63
+ AndroidLaunchApp.flags = {
64
+ ...base_command_1.BaseCommand.baseFlags,
65
+ id: core_1.Flags.string({
66
+ description: 'Android instance ID to target. Defaults to the last created Android instance.',
67
+ }),
68
+ detach: core_1.Flags.boolean({
69
+ char: 'd',
70
+ description: 'Exit right after launching instead of watching until the app exits',
71
+ default: false,
72
+ }),
73
+ mode: core_1.Flags.string({
74
+ description: 'Launch behavior to use when the app may already be running. Default: ForegroundIfRunning.',
75
+ options: ['ForegroundIfRunning', 'RelaunchIfRunning'],
76
+ }),
77
+ };
78
+ exports.default = AndroidLaunchApp;
79
+ //# sourceMappingURL=launch-app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch-app.js","sourceRoot":"","sources":["../../../src/commands/android/launch-app.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,11 @@
1
1
  import { BaseCommand } from '../../base-command';
2
- export default class IosStopMicrophonePlayback extends BaseCommand {
2
+ export default class AndroidTerminateApp extends BaseCommand {
3
3
  static summary: string;
4
4
  static description: string;
5
5
  static examples: string[];
6
+ static args: {
7
+ packageName: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
8
+ };
6
9
  static flags: {
7
10
  id: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
11
  'api-key': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
@@ -14,4 +17,4 @@ export default class IosStopMicrophonePlayback extends BaseCommand {
14
17
  };
15
18
  run(): Promise<void>;
16
19
  }
17
- //# sourceMappingURL=stop-microphone-playback.d.ts.map
20
+ //# sourceMappingURL=terminate-app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminate-app.d.ts","sourceRoot":"","sources":["../../../src/commands/android/terminate-app.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,WAAW;IAC1D,MAAM,CAAC,OAAO,SAAoD;IAClE,MAAM,CAAC,WAAW,SACwJ;IAC1K,MAAM,CAAC,QAAQ,WAGb;IAEF,MAAM,CAAC,IAAI;;MAKT;IAEF,MAAM,CAAC,KAAK;;;;;;;;MAKV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAe3B"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../base-command");
5
+ const instance_client_factory_1 = require("../../lib/instance-client-factory");
6
+ class AndroidTerminateApp extends base_command_1.BaseCommand {
7
+ async run() {
8
+ const { args, flags } = await this.parse(AndroidTerminateApp);
9
+ this.setParsedFlags(flags);
10
+ await this.withAuth(async () => {
11
+ const resolvedInstance = this.resolveAndroidInstance(flags.id);
12
+ const { client, disconnect } = await (0, instance_client_factory_1.getAndroidInstanceClient)(this.client, resolvedInstance);
13
+ try {
14
+ await client.terminateApp(args.packageName);
15
+ }
16
+ finally {
17
+ disconnect();
18
+ }
19
+ this.log(`Terminated ${args.packageName}`);
20
+ });
21
+ }
22
+ }
23
+ AndroidTerminateApp.summary = 'Terminate an app on a running Android instance';
24
+ AndroidTerminateApp.description = 'Stop a running app on an Android instance by package name. This is useful when resetting application state or ending a foreground app before another automation step.';
25
+ AndroidTerminateApp.examples = [
26
+ '<%= config.bin %> android terminate-app com.example.app',
27
+ '<%= config.bin %> android terminate-app com.example.app --id <instance-ID>',
28
+ ];
29
+ AndroidTerminateApp.args = {
30
+ packageName: core_1.Args.string({
31
+ description: 'Package name of the running app to terminate',
32
+ required: true,
33
+ }),
34
+ };
35
+ AndroidTerminateApp.flags = {
36
+ ...base_command_1.BaseCommand.baseFlags,
37
+ id: core_1.Flags.string({
38
+ description: 'Android instance ID to target. Defaults to the last created Android instance.',
39
+ }),
40
+ };
41
+ exports.default = AndroidTerminateApp;
42
+ //# sourceMappingURL=terminate-app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminate-app.js","sourceRoot":"","sources":["../../../src/commands/android/terminate-app.ts"],"names":[],"mappings":";;AAAA,sCAA0C;AAC1C,qDAAiD;AACjD,+EAA6E;AAE7E,MAAqB,mBAAoB,SAAQ,0BAAW;IAuB1D,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC9D,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAE3B,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAC7B,MAAM,gBAAgB,GAAG,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC/D,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,IAAA,kDAAwB,EAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;YAC7F,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC9C,CAAC;oBAAS,CAAC;gBACT,UAAU,EAAE,CAAC;YACf,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC;;AApCM,2BAAO,GAAG,gDAAgD,CAAC;AAC3D,+BAAW,GAChB,uKAAuK,CAAC;AACnK,4BAAQ,GAAG;IAChB,yDAAyD;IACzD,4EAA4E;CAC7E,CAAC;AAEK,wBAAI,GAAG;IACZ,WAAW,EAAE,WAAI,CAAC,MAAM,CAAC;QACvB,WAAW,EAAE,8CAA8C;QAC3D,QAAQ,EAAE,IAAI;KACf,CAAC;CACH,CAAC;AAEK,yBAAK,GAAG;IACb,GAAG,0BAAW,CAAC,SAAS;IACxB,EAAE,EAAE,YAAK,CAAC,MAAM,CAAC;QACf,WAAW,EAAE,+EAA+E;KAC7F,CAAC;CACH,CAAC;kBArBiB,mBAAmB"}
@@ -0,0 +1,20 @@
1
+ import { BaseCommand } from '../../base-command';
2
+ export default class IosAttachXcode extends BaseCommand {
3
+ static summary: string;
4
+ static description: string;
5
+ static examples: string[];
6
+ static args: {
7
+ xcodeId: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
8
+ };
9
+ static flags: {
10
+ create: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ id: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ 'api-key': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
14
+ quiet: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
15
+ workspace: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
16
+ daemon: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
17
+ };
18
+ run(): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=attach-xcode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attach-xcode.d.ts","sourceRoot":"","sources":["../../../src/commands/ios/attach-xcode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAIjD,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,WAAW;IACrD,MAAM,CAAC,OAAO,SAAkD;IAChE,MAAM,CAAC,WAAW,SAG0F;IAE5G,MAAM,CAAC,QAAQ,WAIb;IAEF,MAAM,CAAC,IAAI;;MAKT;IAEF,MAAM,CAAC,KAAK;;;;;;;;MAUV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA+B3B"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../base-command");
5
+ const config_1 = require("../../lib/config");
6
+ const simulator_attach_1 = require("../../lib/simulator-attach");
7
+ class IosAttachXcode extends base_command_1.BaseCommand {
8
+ async run() {
9
+ const { args, flags } = await this.parse(IosAttachXcode);
10
+ this.setParsedFlags(flags);
11
+ await this.withAuth(async () => {
12
+ const simulator = this.resolveIosInstance(flags.id);
13
+ const xcodeTarget = await this.resolveXcodeTarget(args.xcodeId);
14
+ const xcodeInstanceId = xcodeTarget.id;
15
+ const xcodeClient = await this.resolveXcodeClient(xcodeTarget);
16
+ let attachInput;
17
+ if (simulator.apiUrl && simulator.token) {
18
+ attachInput = { apiUrl: simulator.apiUrl, token: simulator.token };
19
+ }
20
+ else {
21
+ const instance = await this.client.iosInstances.get(simulator.id);
22
+ (0, config_1.registerCreatedInstance)(instance);
23
+ attachInput = instance;
24
+ }
25
+ this.info(`Attaching Xcode target ${xcodeInstanceId} to simulator ${simulator.id}...`);
26
+ const result = await xcodeClient.attachSimulator(attachInput);
27
+ if (flags.json) {
28
+ this.outputJson((0, simulator_attach_1.simulatorAttachJson)(simulator.id, xcodeInstanceId, result));
29
+ }
30
+ else if (this.isQuietEnabled()) {
31
+ this.output(xcodeInstanceId);
32
+ }
33
+ else {
34
+ this.output((0, simulator_attach_1.formatSimulatorAttachResult)(simulator.id, xcodeInstanceId, result));
35
+ }
36
+ });
37
+ }
38
+ }
39
+ IosAttachXcode.summary = 'Attach an Xcode instance to an iOS simulator';
40
+ IosAttachXcode.description = 'Attach an Xcode sandbox to an existing iOS simulator so future builds can auto-install on that simulator. ' +
41
+ 'When the Xcode target is omitted, the LIM_XCODE_INSTANCE_URL/LIM_XCODE_INSTANCE_TOKEN pair or the last used ' +
42
+ 'Xcode-capable target is attached; if the simulator credentials are known locally, no API key is needed.';
43
+ IosAttachXcode.examples = [
44
+ '<%= config.bin %> ios attach-xcode',
45
+ '<%= config.bin %> ios attach-xcode <xcode-instance-ID>',
46
+ '<%= config.bin %> ios attach-xcode <xcode-instance-ID> --id <ios-instance-ID>',
47
+ ];
48
+ IosAttachXcode.args = {
49
+ xcodeId: core_1.Args.string({
50
+ description: 'Xcode target to attach. Defaults to the environment-pinned or last used Xcode target.',
51
+ required: false,
52
+ }),
53
+ };
54
+ IosAttachXcode.flags = {
55
+ ...base_command_1.BaseCommand.baseFlags,
56
+ create: core_1.Flags.boolean({
57
+ hidden: true,
58
+ default: false,
59
+ allowNo: true,
60
+ }),
61
+ id: core_1.Flags.string({
62
+ description: 'iOS simulator instance ID to attach. Defaults to the last used iOS simulator.',
63
+ }),
64
+ };
65
+ exports.default = IosAttachXcode;
66
+ //# sourceMappingURL=attach-xcode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attach-xcode.js","sourceRoot":"","sources":["../../../src/commands/ios/attach-xcode.ts"],"names":[],"mappings":";;AAAA,sCAA0C;AAC1C,qDAAiD;AACjD,6CAA2D;AAC3D,iEAA8F;AAE9F,MAAqB,cAAe,SAAQ,0BAAW;IAgCrD,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACzD,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAE3B,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACpD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAChE,MAAM,eAAe,GAAG,WAAW,CAAC,EAAE,CAAC;YACvC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;YAE/D,IAAI,WAA8D,CAAC;YACnE,IAAI,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;gBACxC,WAAW,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC;YACrE,CAAC;iBAAM,CAAC;gBACN,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;gBAClE,IAAA,gCAAuB,EAAC,QAAQ,CAAC,CAAC;gBAClC,WAAW,GAAG,QAAQ,CAAC;YACzB,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,0BAA0B,eAAe,iBAAiB,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;YACvF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;YAE9D,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;gBACf,IAAI,CAAC,UAAU,CAAC,IAAA,sCAAmB,EAAC,SAAS,CAAC,EAAE,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;YAC9E,CAAC;iBAAM,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;gBACjC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,IAAA,8CAA2B,EAAC,SAAS,CAAC,EAAE,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;YAClF,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;;AA7DM,sBAAO,GAAG,8CAA8C,CAAC;AACzD,0BAAW,GAChB,4GAA4G;IAC5G,8GAA8G;IAC9G,yGAAyG,CAAC;AAErG,uBAAQ,GAAG;IAChB,oCAAoC;IACpC,wDAAwD;IACxD,+EAA+E;CAChF,CAAC;AAEK,mBAAI,GAAG;IACZ,OAAO,EAAE,WAAI,CAAC,MAAM,CAAC;QACnB,WAAW,EAAE,uFAAuF;QACpG,QAAQ,EAAE,KAAK;KAChB,CAAC;CACH,CAAC;AAEK,oBAAK,GAAG;IACb,GAAG,0BAAW,CAAC,SAAS;IACxB,MAAM,EAAE,YAAK,CAAC,OAAO,CAAC;QACpB,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,IAAI;KACd,CAAC;IACF,EAAE,EAAE,YAAK,CAAC,MAAM,CAAC;QACf,WAAW,EAAE,+EAA+E;KAC7F,CAAC;CACH,CAAC;kBA9BiB,cAAc"}
@@ -1,10 +1,11 @@
1
1
  import { BaseCommand } from '../../base-command';
2
- export default class IosPlayOnMicrophone extends BaseCommand {
2
+ export default class IosMicrophone extends BaseCommand {
3
3
  static summary: string;
4
4
  static description: string;
5
5
  static examples: string[];
6
6
  static args: {
7
- path: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ action: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
8
+ path: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
8
9
  };
9
10
  static flags: {
10
11
  id: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
@@ -18,4 +19,4 @@ export default class IosPlayOnMicrophone extends BaseCommand {
18
19
  };
19
20
  run(): Promise<void>;
20
21
  }
21
- //# sourceMappingURL=play-on-microphone.d.ts.map
22
+ //# sourceMappingURL=microphone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"microphone.d.ts","sourceRoot":"","sources":["../../../src/commands/ios/microphone.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW;IACpD,MAAM,CAAC,OAAO,SAAgE;IAC9E,MAAM,CAAC,WAAW,SAG6C;IAE/D,MAAM,CAAC,QAAQ,WAKb;IAEF,MAAM,CAAC,IAAI;;;MAUT;IAEF,MAAM,CAAC,KAAK;;;;;;;;;MASV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA+C3B"}
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const fs_1 = __importDefault(require("fs"));
7
+ const path_1 = __importDefault(require("path"));
8
+ const core_1 = require("@oclif/core");
9
+ const base_command_1 = require("../../base-command");
10
+ const instance_client_factory_1 = require("../../lib/instance-client-factory");
11
+ class IosMicrophone extends base_command_1.BaseCommand {
12
+ async run() {
13
+ const { args, flags } = await this.parse(IosMicrophone);
14
+ this.setParsedFlags(flags);
15
+ await this.withAuth(async () => {
16
+ const resolvedInstance = this.resolveIosInstance(flags.id);
17
+ const { client, disconnect } = await (0, instance_client_factory_1.getIosInstanceClient)(this.client, resolvedInstance);
18
+ try {
19
+ if (args.action === 'stop') {
20
+ await client.stopMicrophonePlayback();
21
+ if (flags.json) {
22
+ this.outputJson({ stopped: true });
23
+ }
24
+ else {
25
+ this.output('Stopped microphone playback');
26
+ }
27
+ return;
28
+ }
29
+ if (!args.path) {
30
+ this.error('The `play` action requires an audio file path.');
31
+ }
32
+ const localPath = path_1.default.resolve(args.path);
33
+ if (!fs_1.default.existsSync(localPath)) {
34
+ this.error(`File not found: ${localPath}`);
35
+ }
36
+ const stat = fs_1.default.statSync(localPath);
37
+ if (!stat.isFile()) {
38
+ this.error(`Path is not a file: ${localPath}`);
39
+ }
40
+ const remoteName = path_1.default.basename(localPath);
41
+ this.info(`Uploading ${remoteName}...`);
42
+ await client.pushFile(localPath, remoteName);
43
+ const result = await client.playOnMicrophone(remoteName, { once: flags.once });
44
+ if (flags.json) {
45
+ this.outputJson(result);
46
+ }
47
+ else {
48
+ this.output(`Playing ${remoteName} on microphone (duration=${result.duration}us, once=${result.once})`);
49
+ }
50
+ }
51
+ finally {
52
+ disconnect();
53
+ }
54
+ });
55
+ }
56
+ }
57
+ IosMicrophone.summary = 'Control the simulated microphone of a running iOS instance';
58
+ IosMicrophone.description = 'Upload a local audio file (WAV/MP3/M4A/AAC) and play it as mocked microphone input on a running iOS instance. ' +
59
+ 'Playback loops until stopped by default; use --once to play a single pass. ' +
60
+ 'Use the `stop` action to return the microphone to silence.';
61
+ IosMicrophone.examples = [
62
+ '<%= config.bin %> ios microphone play ./sample.wav',
63
+ '<%= config.bin %> ios microphone play ./sample.mp3 --once',
64
+ '<%= config.bin %> ios microphone play ./sample.wav --id <instance-ID>',
65
+ '<%= config.bin %> ios microphone stop',
66
+ ];
67
+ IosMicrophone.args = {
68
+ action: core_1.Args.string({
69
+ description: 'Microphone action: `play` plays an audio file and `stop` stops mocked input',
70
+ required: true,
71
+ options: ['play', 'stop'],
72
+ }),
73
+ path: core_1.Args.string({
74
+ description: 'Local audio file to play as microphone input (required for the `play` action)',
75
+ required: false,
76
+ }),
77
+ };
78
+ IosMicrophone.flags = {
79
+ ...base_command_1.BaseCommand.baseFlags,
80
+ id: core_1.Flags.string({
81
+ description: 'iOS instance ID to target. Defaults to the last created iOS instance.',
82
+ }),
83
+ once: core_1.Flags.boolean({
84
+ description: 'Play the audio file once instead of looping it',
85
+ default: false,
86
+ }),
87
+ };
88
+ exports.default = IosMicrophone;
89
+ //# sourceMappingURL=microphone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"microphone.js","sourceRoot":"","sources":["../../../src/commands/ios/microphone.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { AppExitInfo } from '@limrun/api';
2
+ /**
3
+ * Renders an Android appExit notification as human-readable text: the exit
4
+ * reason, crash or ANR details when present, and the recent app log tail
5
+ * delivered with the event.
6
+ */
7
+ export declare function formatAppExit(info: AppExitInfo, logs: string[]): string;
8
+ //# sourceMappingURL=format-app-exit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-app-exit.d.ts","sourceRoot":"","sources":["../../src/lib/format-app-exit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAuBvE"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatAppExit = formatAppExit;
4
+ /**
5
+ * Renders an Android appExit notification as human-readable text: the exit
6
+ * reason, crash or ANR details when present, and the recent app log tail
7
+ * delivered with the event.
8
+ */
9
+ function formatAppExit(info, logs) {
10
+ const lines = [`${info.packageName} exited (reason: ${info.reason})`];
11
+ if (info.crash) {
12
+ lines.push(`Crash in ${info.crash.processName} (pid ${info.crash.pid}): ${info.crash.shortMsg}`);
13
+ if (info.crash.stackTrace) {
14
+ lines.push(info.crash.stackTrace.trimEnd());
15
+ }
16
+ }
17
+ if (info.anr) {
18
+ lines.push(`ANR in ${info.anr.processName} (pid ${info.anr.pid})`);
19
+ if (info.anr.processStats) {
20
+ lines.push(info.anr.processStats.trimEnd());
21
+ }
22
+ }
23
+ if (logs.length > 0) {
24
+ lines.push(`--- Recent app logs (${logs.length} lines) ---`);
25
+ lines.push(...logs);
26
+ }
27
+ return lines.join('\n');
28
+ }
29
+ //# sourceMappingURL=format-app-exit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-app-exit.js","sourceRoot":"","sources":["../../src/lib/format-app-exit.ts"],"names":[],"mappings":";;AAOA,sCAuBC;AA5BD;;;;GAIG;AACH,SAAgB,aAAa,CAAC,IAAiB,EAAE,IAAc;IAC7D,MAAM,KAAK,GAAa,CAAC,GAAG,IAAI,CAAC,WAAW,oBAAoB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IAEhF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,WAAW,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjG,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;YAC1B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,GAAG,CAAC,WAAW,SAAS,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;QACnE,IAAI,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YAC1B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,wBAAwB,IAAI,CAAC,MAAM,aAAa,CAAC,CAAC;QAC7D,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=format-app-exit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-app-exit.test.d.ts","sourceRoot":"","sources":["../../src/lib/format-app-exit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const format_app_exit_1 = require("./format-app-exit");
4
+ describe('formatAppExit', () => {
5
+ it('formats a plain exit with logs', () => {
6
+ const info = { packageName: 'com.example.app', reason: 'exit' };
7
+ const out = (0, format_app_exit_1.formatAppExit)(info, ['line one', 'line two']);
8
+ expect(out).toContain('com.example.app exited (reason: exit)');
9
+ expect(out).toContain('--- Recent app logs (2 lines) ---');
10
+ expect(out).toContain('line one');
11
+ expect(out.endsWith('line two')).toBe(true);
12
+ });
13
+ it('formats a crash with stack trace before the logs', () => {
14
+ const info = {
15
+ packageName: 'com.example.app',
16
+ reason: 'crash',
17
+ crash: {
18
+ processName: 'com.example.app',
19
+ pid: 4242,
20
+ shortMsg: 'java.lang.RuntimeException',
21
+ longMsg: 'java.lang.RuntimeException: boom',
22
+ stackTrace: 'java.lang.RuntimeException: boom\n\tat MainActivity.onCreate\n',
23
+ timeMillis: 1700000000000,
24
+ },
25
+ };
26
+ const out = (0, format_app_exit_1.formatAppExit)(info, ['log line']);
27
+ expect(out).toContain('exited (reason: crash)');
28
+ expect(out).toContain('Crash in com.example.app (pid 4242): java.lang.RuntimeException');
29
+ expect(out).toContain('\tat MainActivity.onCreate');
30
+ expect(out.indexOf('MainActivity')).toBeLessThan(out.indexOf('Recent app logs'));
31
+ });
32
+ it('formats an ANR with process stats', () => {
33
+ const info = {
34
+ packageName: 'com.example.app',
35
+ reason: 'anr',
36
+ anr: { processName: 'com.example.app', pid: 77, processStats: 'CPU usage: 99%\n' },
37
+ };
38
+ const out = (0, format_app_exit_1.formatAppExit)(info, []);
39
+ expect(out).toContain('exited (reason: anr)');
40
+ expect(out).toContain('ANR in com.example.app (pid 77)');
41
+ expect(out).toContain('CPU usage: 99%');
42
+ expect(out).not.toContain('Recent app logs');
43
+ });
44
+ it('omits the log section when no logs were delivered', () => {
45
+ const info = { packageName: 'com.example.app', reason: 'terminated' };
46
+ expect((0, format_app_exit_1.formatAppExit)(info, [])).toBe('com.example.app exited (reason: terminated)');
47
+ });
48
+ });
49
+ //# sourceMappingURL=format-app-exit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-app-exit.test.js","sourceRoot":"","sources":["../../src/lib/format-app-exit.test.ts"],"names":[],"mappings":";;AAAA,uDAAkD;AAGlD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,IAAI,GAAgB,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC7E,MAAM,GAAG,GAAG,IAAA,+BAAa,EAAC,IAAI,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAC;QAC/D,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,mCAAmC,CAAC,CAAC;QAC3D,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,IAAI,GAAgB;YACxB,WAAW,EAAE,iBAAiB;YAC9B,MAAM,EAAE,OAAO;YACf,KAAK,EAAE;gBACL,WAAW,EAAE,iBAAiB;gBAC9B,GAAG,EAAE,IAAI;gBACT,QAAQ,EAAE,4BAA4B;gBACtC,OAAO,EAAE,kCAAkC;gBAC3C,UAAU,EAAE,gEAAgE;gBAC5E,UAAU,EAAE,aAAa;aAC1B;SACF,CAAC;QACF,MAAM,GAAG,GAAG,IAAA,+BAAa,EAAC,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,iEAAiE,CAAC,CAAC;QACzF,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC;QACpD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,IAAI,GAAgB;YACxB,WAAW,EAAE,iBAAiB;YAC9B,MAAM,EAAE,KAAK;YACb,GAAG,EAAE,EAAE,WAAW,EAAE,iBAAiB,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,kBAAkB,EAAE;SACnF,CAAC;QACF,MAAM,GAAG,GAAG,IAAA,+BAAa,EAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;QACzD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,IAAI,GAAgB,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;QACnF,MAAM,CAAC,IAAA,+BAAa,EAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lim",
3
- "version": "0.28.4",
3
+ "version": "0.28.6",
4
4
  "description": "Use remote XCode, Gradle, iOS Simulator, Android Emulator and more to build and test apps from Linux, Windows or macOS.",
5
5
  "bin": {
6
6
  "lim": "./bin/run.js"
@@ -54,7 +54,7 @@
54
54
  "topicSeparator": " ",
55
55
  "topics": {
56
56
  "android": {
57
- "description": "Execute any task on remote Android Emulators: create, list, get, delete, connect, sync, screenshot, tap, tap-element, find-element, element-tree, type, press-key, scroll, open-url, install-app, record, play-on-microphone, set-wifi-bandwidth"
57
+ "description": "Execute any task on remote Android Emulators: create, list, get, delete, connect, sync, screenshot, tap, tap-element, find-element, element-tree, type, press-key, scroll, open-url, install-app, launch-app, terminate-app, record, play-on-microphone, set-wifi-bandwidth"
58
58
  },
59
59
  "asset": {
60
60
  "description": "Upload, download, list, inspect, and delete files that can be used by iOS & Android as pre-installed apps: push, pull, list, delete"
@@ -66,7 +66,7 @@
66
66
  "description": "Build Android projects on cloud gradle sandboxes"
67
67
  },
68
68
  "ios": {
69
- "description": "Execute any task on remote iOS Simulators: create, list, get, delete, info, list-apps, launch-app, terminate-app, app-log, syslog, sync, screenshot, tap, tap-element, element-tree, type, press-key, toggle-keyboard, scroll, open-url, install-app, keychain, record, perform, ls, push-file, pull-file, delete-file, simctl, cp, xcrun, xcodebuild, lsof, reverse"
69
+ "description": "Execute any task on remote iOS Simulators: create, list, get, delete, attach-xcode, info, list-apps, launch-app, terminate-app, app-log, syslog, sync, screenshot, tap, tap-element, element-tree, type, press-key, toggle-keyboard, scroll, open-url, install-app, keychain, record, camera, microphone, perform, ls, push-file, pull-file, delete-file, simctl, cp, xcrun, xcodebuild, lsof, reverse"
70
70
  },
71
71
  "session": {
72
72
  "description": "Manage persistent background sessions for device interaction: start, status, stop. Sessions are used to execute commands on remote devices without the need to reconnect to the device after each command."
@@ -1 +0,0 @@
1
- {"version":3,"file":"play-on-microphone.d.ts","sourceRoot":"","sources":["../../../src/commands/ios/play-on-microphone.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,WAAW;IAC1D,MAAM,CAAC,OAAO,SAA2E;IACzF,MAAM,CAAC,WAAW,SAEgG;IAElH,MAAM,CAAC,QAAQ,WAIb;IAEF,MAAM,CAAC,IAAI;;MAKT;IAEF,MAAM,CAAC,KAAK;;;;;;;;;MASV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAkC3B"}
@@ -1,69 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const fs_1 = __importDefault(require("fs"));
7
- const path_1 = __importDefault(require("path"));
8
- const core_1 = require("@oclif/core");
9
- const base_command_1 = require("../../base-command");
10
- const instance_client_factory_1 = require("../../lib/instance-client-factory");
11
- class IosPlayOnMicrophone extends base_command_1.BaseCommand {
12
- async run() {
13
- const { args, flags } = await this.parse(IosPlayOnMicrophone);
14
- this.setParsedFlags(flags);
15
- await this.withAuth(async () => {
16
- const localPath = path_1.default.resolve(args.path);
17
- if (!fs_1.default.existsSync(localPath)) {
18
- this.error(`File not found: ${localPath}`);
19
- }
20
- const stat = fs_1.default.statSync(localPath);
21
- if (!stat.isFile()) {
22
- this.error(`Path is not a file: ${localPath}`);
23
- }
24
- const resolvedInstance = this.resolveIosInstance(flags.id);
25
- const { client, disconnect } = await (0, instance_client_factory_1.getIosInstanceClient)(this.client, resolvedInstance);
26
- try {
27
- const remoteName = path_1.default.basename(localPath);
28
- this.info(`Uploading ${remoteName}...`);
29
- await client.pushFile(localPath, remoteName);
30
- const result = await client.playOnMicrophone(remoteName, { once: flags.once });
31
- if (flags.json) {
32
- this.outputJson(result);
33
- }
34
- else {
35
- this.output(`Playing ${remoteName} on microphone (duration=${result.duration}us, once=${result.once})`);
36
- }
37
- }
38
- finally {
39
- disconnect();
40
- }
41
- });
42
- }
43
- }
44
- IosPlayOnMicrophone.summary = 'Play a local audio file as microphone input on a running iOS instance';
45
- IosPlayOnMicrophone.description = 'Upload a local audio file (WAV/MP3/M4A/AAC) to the simulator, then play it as mocked microphone input. ' +
46
- 'Loops until stopped by default; use --once to play a single pass. Use `ios stop-microphone-playback` to stop.';
47
- IosPlayOnMicrophone.examples = [
48
- '<%= config.bin %> ios play-on-microphone ./sample.wav',
49
- '<%= config.bin %> ios play-on-microphone ./sample.mp3 --once',
50
- '<%= config.bin %> ios play-on-microphone ./sample.wav --id <instance-ID>',
51
- ];
52
- IosPlayOnMicrophone.args = {
53
- path: core_1.Args.string({
54
- description: 'Local audio file path to upload and play as microphone input',
55
- required: true,
56
- }),
57
- };
58
- IosPlayOnMicrophone.flags = {
59
- ...base_command_1.BaseCommand.baseFlags,
60
- id: core_1.Flags.string({
61
- description: 'iOS instance ID to target. Defaults to the last created iOS instance.',
62
- }),
63
- once: core_1.Flags.boolean({
64
- description: 'Play the audio file once instead of looping it',
65
- default: false,
66
- }),
67
- };
68
- exports.default = IosPlayOnMicrophone;
69
- //# sourceMappingURL=play-on-microphone.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"play-on-microphone.js","sourceRoot":"","sources":["../../../src/commands/ios/play-on-microphone.ts"],"names":[],"mappings":";;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,sCAA0C;AAC1C,qDAAiD;AACjD,+EAAyE;AAEzE,MAAqB,mBAAoB,SAAQ,0BAAW;IA8B1D,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC9D,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAE3B,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAC7B,MAAM,SAAS,GAAG,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC9B,IAAI,CAAC,KAAK,CAAC,mBAAmB,SAAS,EAAE,CAAC,CAAC;YAC7C,CAAC;YACD,MAAM,IAAI,GAAG,YAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;gBACnB,IAAI,CAAC,KAAK,CAAC,uBAAuB,SAAS,EAAE,CAAC,CAAC;YACjD,CAAC;YAED,MAAM,gBAAgB,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC3D,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,IAAA,8CAAoB,EAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;YACzF,IAAI,CAAC;gBACH,MAAM,UAAU,GAAG,cAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;gBAC5C,IAAI,CAAC,IAAI,CAAC,aAAa,UAAU,KAAK,CAAC,CAAC;gBACxC,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;gBAC7C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;gBAE/E,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;oBACf,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;gBAC1B,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,MAAM,CACT,WAAW,UAAU,4BAA4B,MAAM,CAAC,QAAQ,YAAY,MAAM,CAAC,IAAI,GAAG,CAC3F,CAAC;gBACJ,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,UAAU,EAAE,CAAC;YACf,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;;AA9DM,2BAAO,GAAG,uEAAuE,CAAC;AAClF,+BAAW,GAChB,yGAAyG;IACzG,+GAA+G,CAAC;AAE3G,4BAAQ,GAAG;IAChB,uDAAuD;IACvD,8DAA8D;IAC9D,0EAA0E;CAC3E,CAAC;AAEK,wBAAI,GAAG;IACZ,IAAI,EAAE,WAAI,CAAC,MAAM,CAAC;QAChB,WAAW,EAAE,8DAA8D;QAC3E,QAAQ,EAAE,IAAI;KACf,CAAC;CACH,CAAC;AAEK,yBAAK,GAAG;IACb,GAAG,0BAAW,CAAC,SAAS;IACxB,EAAE,EAAE,YAAK,CAAC,MAAM,CAAC;QACf,WAAW,EAAE,uEAAuE;KACrF,CAAC;IACF,IAAI,EAAE,YAAK,CAAC,OAAO,CAAC;QAClB,WAAW,EAAE,gDAAgD;QAC7D,OAAO,EAAE,KAAK;KACf,CAAC;CACH,CAAC;kBA5BiB,mBAAmB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"stop-microphone-playback.d.ts","sourceRoot":"","sources":["../../../src/commands/ios/stop-microphone-playback.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,MAAM,CAAC,OAAO,OAAO,yBAA0B,SAAQ,WAAW;IAChE,MAAM,CAAC,OAAO,SAA+D;IAC7E,MAAM,CAAC,WAAW,SAC0E;IAE5F,MAAM,CAAC,QAAQ,WAGb;IAEF,MAAM,CAAC,KAAK;;;;;;;;MAKV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAmB3B"}
@@ -1,41 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const core_1 = require("@oclif/core");
4
- const base_command_1 = require("../../base-command");
5
- const instance_client_factory_1 = require("../../lib/instance-client-factory");
6
- class IosStopMicrophonePlayback extends base_command_1.BaseCommand {
7
- async run() {
8
- const { flags } = await this.parse(IosStopMicrophonePlayback);
9
- this.setParsedFlags(flags);
10
- await this.withAuth(async () => {
11
- const resolvedInstance = this.resolveIosInstance(flags.id);
12
- const { client, disconnect } = await (0, instance_client_factory_1.getIosInstanceClient)(this.client, resolvedInstance);
13
- try {
14
- await client.stopMicrophonePlayback();
15
- if (flags.json) {
16
- this.outputJson({ stopped: true });
17
- }
18
- else {
19
- this.output('Stopped microphone playback');
20
- }
21
- }
22
- finally {
23
- disconnect();
24
- }
25
- });
26
- }
27
- }
28
- IosStopMicrophonePlayback.summary = 'Stop mocked microphone playback on a running iOS instance';
29
- IosStopMicrophonePlayback.description = 'Stops audio started with `ios play-on-microphone`; the microphone goes back to silence.';
30
- IosStopMicrophonePlayback.examples = [
31
- '<%= config.bin %> ios stop-microphone-playback',
32
- '<%= config.bin %> ios stop-microphone-playback --id <instance-ID>',
33
- ];
34
- IosStopMicrophonePlayback.flags = {
35
- ...base_command_1.BaseCommand.baseFlags,
36
- id: core_1.Flags.string({
37
- description: 'iOS instance ID to target. Defaults to the last created iOS instance.',
38
- }),
39
- };
40
- exports.default = IosStopMicrophonePlayback;
41
- //# sourceMappingURL=stop-microphone-playback.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stop-microphone-playback.js","sourceRoot":"","sources":["../../../src/commands/ios/stop-microphone-playback.ts"],"names":[],"mappings":";;AAAA,sCAAoC;AACpC,qDAAiD;AACjD,+EAAyE;AAEzE,MAAqB,yBAA0B,SAAQ,0BAAW;IAiBhE,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC9D,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAE3B,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAC7B,MAAM,gBAAgB,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC3D,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,IAAA,8CAAoB,EAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;YACzF,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,sBAAsB,EAAE,CAAC;gBACtC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;oBACf,IAAI,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBACrC,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,UAAU,EAAE,CAAC;YACf,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;;AAlCM,iCAAO,GAAG,2DAA2D,CAAC;AACtE,qCAAW,GAChB,yFAAyF,CAAC;AAErF,kCAAQ,GAAG;IAChB,gDAAgD;IAChD,mEAAmE;CACpE,CAAC;AAEK,+BAAK,GAAG;IACb,GAAG,0BAAW,CAAC,SAAS;IACxB,EAAE,EAAE,YAAK,CAAC,MAAM,CAAC;QACf,WAAW,EAAE,uEAAuE;KACrF,CAAC;CACH,CAAC;kBAfiB,yBAAyB"}