runcloud 0.2.198 → 0.2.200

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 CHANGED
@@ -64,6 +64,8 @@ runcloud ios create --model iphone --install ./MyApp.app # boot a simulator an
64
64
  runcloud ios list # list active sessions
65
65
  runcloud ios get <id> # inspect a session (viewer URL, status)
66
66
  runcloud ios open-url myapp://path --id <id> # open a URL or deep link
67
+ runcloud ios settings <id> --json # read device settings (on-screen keyboard mode)
68
+ runcloud ios settings <id> --soft-keyboard hidden # auto, hidden, or shown
67
69
  runcloud ios tap <id> 0.5 0.75 # normalized top-left display coordinates
68
70
  runcloud ios type-text <id> "Hello from iOS!" # printable US ASCII, tab, and line feed
69
71
  runcloud ios accessibility-tree <id> --json # read the current typed accessibility hierarchy
@@ -84,6 +86,7 @@ runcloud ios delete <id> # release the session
84
86
  runcloud android create --model pixel
85
87
  runcloud android swipe <id> 0.5 0.8 0.5 0.2 --duration 250
86
88
  runcloud android press-key <id> enter
89
+ runcloud android settings <id> --soft-keyboard auto --json
87
90
  runcloud android accessibility-tree <id> --json
88
91
  runcloud android camera inject <id> ./quadrants.mp4 --bundle-id com.example.Camera
89
92
  runcloud android mic inject <id> ./tone.wav --bundle-id com.example.Recorder
@@ -50,6 +50,10 @@ export async function runDomainCheck(client, domainNames, log = console.log) {
50
50
  const candidates = result.domains ?? [];
51
51
  log(candidates.length ? candidates.map(summarizeDomain).join('\n') : 'No results.');
52
52
  }
53
+ export function checkoutReturnUrl(appUrl, projectId, domain, outcome) {
54
+ const query = new URLSearchParams({ domain_checkout: outcome, domain });
55
+ return `${appUrl}/projects/${encodeURIComponent(projectId)}/deploy?${query}`;
56
+ }
53
57
  export async function runDomainBuy(client, projectId, domainName, opts, log = console.log, confirmPurchase = confirm) {
54
58
  const quoteResult = (await client.post(`/projects/${projectId}/domains/registrations/quote`, {
55
59
  domain: domainName,
@@ -67,8 +71,8 @@ export async function runDomainBuy(client, projectId, domainName, opts, log = co
67
71
  const result = (await client.post(`/projects/${projectId}/domains/registrations/checkout`, {
68
72
  domain: domainName,
69
73
  years: opts.years,
70
- success_url: `${appUrl}/project/${projectId}/website?domain_checkout=success`,
71
- cancel_url: `${appUrl}/project/${projectId}/website?domain_checkout=cancel`,
74
+ success_url: checkoutReturnUrl(appUrl, projectId, domainName, 'success'),
75
+ cancel_url: checkoutReturnUrl(appUrl, projectId, domainName, 'cancel'),
72
76
  }));
73
77
  if (!result.checkout_url)
74
78
  throw new Error('Backend did not return a checkout URL.');
@@ -1053,6 +1053,54 @@ async function setSimulatorSessionLocation(platform, sessionId, point) {
1053
1053
  throw error;
1054
1054
  }
1055
1055
  }
1056
+ const SOFT_KEYBOARD_MODES = ['auto', 'hidden', 'shown'];
1057
+ function parseSoftKeyboardMode(value) {
1058
+ if (SOFT_KEYBOARD_MODES.includes(value))
1059
+ return value;
1060
+ throw new InvalidArgumentError(`must be one of ${SOFT_KEYBOARD_MODES.join(', ')}`);
1061
+ }
1062
+ async function simulatorSessionSettings(platform, sessionId, softKeyboard) {
1063
+ const path = `/run-cloud/${platform}/${encodeURIComponent(sessionId)}/settings`;
1064
+ try {
1065
+ const response = (softKeyboard ? await client().patch(path, { softKeyboard }) : await client().get(path));
1066
+ const result = typeof response === 'object' && response !== null && !Array.isArray(response)
1067
+ ? response
1068
+ : {};
1069
+ if (result.ok !== true
1070
+ || result.platform !== platform
1071
+ || result.sessionId !== sessionId
1072
+ || !SOFT_KEYBOARD_MODES.includes(result.softKeyboard)
1073
+ || (softKeyboard !== undefined && result.softKeyboard !== softKeyboard)) {
1074
+ throw new ApiError(0, 'Simulator settings returned an invalid acknowledgement', path, {
1075
+ code: 'keyboard_setting_invalid_response',
1076
+ retryable: true,
1077
+ sessionId,
1078
+ platform,
1079
+ action: 'settings',
1080
+ });
1081
+ }
1082
+ return result;
1083
+ }
1084
+ catch (error) {
1085
+ if (error instanceof ApiTransportError) {
1086
+ throw new ApiError(0, 'Simulator settings could not reach the run.cloud API', path, {
1087
+ code: 'keyboard_setting_transport_error',
1088
+ retryable: true,
1089
+ sessionId,
1090
+ platform,
1091
+ action: 'settings',
1092
+ });
1093
+ }
1094
+ if (error instanceof ApiError) {
1095
+ Object.assign(error, {
1096
+ sessionId: error.sessionId ?? sessionId,
1097
+ platform: error.platform ?? platform,
1098
+ action: error.action ?? 'settings',
1099
+ });
1100
+ }
1101
+ throw error;
1102
+ }
1103
+ }
1056
1104
  function registerSimulatorCommands(program, platform) {
1057
1105
  const label = platform === 'android' ? 'Android emulator' : 'iOS simulator';
1058
1106
  const article = platform === 'android' ? 'an' : 'an';
@@ -1180,6 +1228,15 @@ function registerSimulatorCommands(program, platform) {
1180
1228
  .action((id, opts) => action(async () => {
1181
1229
  print(await setSimulatorSessionLocation(platform, id, null), opts);
1182
1230
  }, opts));
1231
+ simulator
1232
+ .command('settings')
1233
+ .description(`Show or change the device settings of ${article} ${label} session`)
1234
+ .argument('<id>', 'session id')
1235
+ .option('--soft-keyboard <mode>', 'on-screen keyboard: auto (hide while a hardware keyboard types), hidden, or shown', parseSoftKeyboardMode)
1236
+ .option('--json', 'output JSON', false)
1237
+ .action((id, opts) => action(async () => {
1238
+ print(await simulatorSessionSettings(platform, id, opts.softKeyboard), opts);
1239
+ }, opts));
1183
1240
  addInteractionOptions(simulator
1184
1241
  .command('tap')
1185
1242
  .description(`Tap normalized display coordinates in ${article} ${label} session`)
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const CLI_VERSION = '0.2.198';
1
+ export const CLI_VERSION = '0.2.200';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runcloud",
3
- "version": "0.2.198",
3
+ "version": "0.2.200",
4
4
  "description": "Create and control run.cloud remote mobile simulators and cloud sandboxes",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
Binary file
@@ -40,7 +40,7 @@ runcloud ios get "$SESSION_ID" --json
40
40
  ```
41
41
 
42
42
  Replace `ios` with `android` for an Android artifact. The shared lifecycle is
43
- `create`, `list`, `get`, `open-url`, `location set|clear`, `logs`, and `delete`. Use `--json` whenever
43
+ `create`, `list`, `get`, `open-url`, `location set|clear`, `settings`, `logs`, and `delete`. Use `--json` whenever
44
44
  another program consumes output, and inspect `runcloud ios|android --help` for
45
45
  create and log options.
46
46
 
Binary file