runcloud 0.2.197 → 0.2.198

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.
@@ -1,4 +1,5 @@
1
1
  import { InvalidArgumentError, Option } from 'commander';
2
+ import { DEFAULT_SIMULATOR_INTERACTION_TIMEOUT_MS as DEFAULT_INTERACTION_TIMEOUT_MS, SIMULATOR_BUTTONS, SIMULATOR_INTERACTION_LIMITS as LIMITS, SIMULATOR_KEY_MODIFIERS, SIMULATOR_KEYS, SIMULATOR_ORIENTATIONS, SIMULATOR_RENDER_DEBUG_OPTIONS, } from '@run-cloud/sdk';
2
3
  import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';
3
4
  import { basename, dirname, extname, join, resolve } from 'node:path';
4
5
  import { homedir } from 'node:os';
@@ -23,31 +24,6 @@ export function runCloudIosOptions(opts) {
23
24
  },
24
25
  };
25
26
  }
26
- export const SIMULATOR_KEYS = [
27
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
28
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
29
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
30
- 'enter', 'escape', 'backspace', 'tab', 'space', 'minus', 'equal',
31
- 'bracketLeft', 'bracketRight', 'backslash', 'semicolon', 'quote', 'backquote',
32
- 'comma', 'period', 'slash', 'capsLock',
33
- 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', 'f11', 'f12',
34
- 'printScreen', 'scrollLock', 'pause', 'insert', 'home', 'pageUp', 'delete', 'end',
35
- 'pageDown', 'arrowRight', 'arrowLeft', 'arrowDown', 'arrowUp', 'numLock',
36
- 'numpadDivide', 'numpadMultiply', 'numpadSubtract', 'numpadAdd', 'numpadEnter',
37
- 'numpad0', 'numpad1', 'numpad2', 'numpad3', 'numpad4', 'numpad5', 'numpad6',
38
- 'numpad7', 'numpad8', 'numpad9', 'numpadDecimal',
39
- ];
40
- export const SIMULATOR_BUTTONS = [
41
- 'home', 'back', 'appSwitcher', 'recents', 'power', 'volumeUp', 'volumeDown',
42
- 'menu', 'sideButton', 'actionButton', 'digitalCrown',
43
- ];
44
- export const SIMULATOR_RENDER_DEBUG_OPTIONS = [
45
- 'colorBlendedLayers',
46
- 'colorCopiedImages',
47
- 'colorMisalignedImages',
48
- 'colorOffscreenRendered',
49
- 'slowAnimations',
50
- ];
51
27
  export const SIMULATOR_INTERACTION_ERROR_CODES = [
52
28
  'invalid_interaction',
53
29
  'active_session_not_found',
@@ -118,7 +94,6 @@ function normalizedAccessibilityErrorCode(value) {
118
94
  ? value
119
95
  : 'accessibility_unavailable';
120
96
  }
121
- const DEFAULT_INTERACTION_TIMEOUT_MS = 15_000;
122
97
  const DEFAULT_ACCESSIBILITY_TIMEOUT_MS = 20_000;
123
98
  const INTERACTION_RESPONSE_MARGIN_MS = 250;
124
99
  const REQUEST_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
@@ -243,8 +218,8 @@ function finiteInRange(raw, name, min, max) {
243
218
  }
244
219
  function normalizedPoint(x, y, name) {
245
220
  return {
246
- x: finiteInRange(x, `${name} x`, 0, 1),
247
- y: finiteInRange(y, `${name} y`, 0, 1),
221
+ x: finiteInRange(x, `${name} x`, LIMITS.coordinate.min, LIMITS.coordinate.max),
222
+ y: finiteInRange(y, `${name} y`, LIMITS.coordinate.min, LIMITS.coordinate.max),
248
223
  };
249
224
  }
250
225
  function simulatorKey(raw) {
@@ -258,10 +233,9 @@ function simulatorButton(raw) {
258
233
  throw new Error(`Unknown simulator button: ${raw}. Choose one of: ${SIMULATOR_BUTTONS.join(', ')}.`);
259
234
  }
260
235
  function simulatorOrientation(raw) {
261
- if (raw === 'portrait' || raw === 'portrait_upside_down' || raw === 'landscape_left' || raw === 'landscape_right') {
236
+ if (SIMULATOR_ORIENTATIONS.includes(raw))
262
237
  return raw;
263
- }
264
- throw new Error(`Unknown orientation: ${raw}. Choose portrait, portrait_upside_down, landscape_left, or landscape_right.`);
238
+ throw new Error(`Unknown orientation: ${raw}. Choose one of: ${SIMULATOR_ORIENTATIONS.join(', ')}.`);
265
239
  }
266
240
  function renderDebugOption(raw) {
267
241
  if (SIMULATOR_RENDER_DEBUG_OPTIONS.includes(raw)) {
@@ -290,12 +264,12 @@ function assertInteraction(interaction, timeoutMs) {
290
264
  return;
291
265
  case 'swipe':
292
266
  if (interaction.durationMs !== undefined) {
293
- integerInRange(String(interaction.durationMs), '--duration', 50, 30_000);
267
+ integerInRange(String(interaction.durationMs), '--duration', LIMITS.swipeDurationMs.min, LIMITS.swipeDurationMs.max);
294
268
  }
295
269
  return;
296
270
  case 'gesture': {
297
- if (interaction.steps.length < 2 || interaction.steps.length > 1_000) {
298
- throw new Error('--steps must contain from 2 to 1000 gesture steps');
271
+ if (interaction.steps.length < LIMITS.gestureSteps.min || interaction.steps.length > LIMITS.gestureSteps.max) {
272
+ throw new Error(`--steps must contain from ${LIMITS.gestureSteps.min} to ${LIMITS.gestureSteps.max} gesture steps`);
299
273
  }
300
274
  let pointCount;
301
275
  let totalDelayMs = 0;
@@ -306,7 +280,7 @@ function assertInteraction(interaction, timeoutMs) {
306
280
  if ((index === interaction.steps.length - 1) !== (step.phase === 'end')) {
307
281
  throw new Error('Gesture steps must end with end and contain no earlier end phase');
308
282
  }
309
- if (step.points.length !== 1 && step.points.length !== 2) {
283
+ if (step.points.length < LIMITS.gesturePoints.min || step.points.length > LIMITS.gesturePoints.max) {
310
284
  throw new Error('Each gesture step must contain one or two points');
311
285
  }
312
286
  if (pointCount === undefined)
@@ -315,14 +289,14 @@ function assertInteraction(interaction, timeoutMs) {
315
289
  throw new Error('Every gesture step must use the same number of points');
316
290
  }
317
291
  for (const point of step.points) {
318
- finiteInRange(String(point.x), 'gesture x', 0, 1);
319
- finiteInRange(String(point.y), 'gesture y', 0, 1);
292
+ finiteInRange(String(point.x), 'gesture x', LIMITS.coordinate.min, LIMITS.coordinate.max);
293
+ finiteInRange(String(point.y), 'gesture y', LIMITS.coordinate.min, LIMITS.coordinate.max);
320
294
  }
321
295
  if (step.delayMs !== undefined) {
322
296
  if (index === interaction.steps.length - 1 && step.delayMs !== 0) {
323
297
  throw new Error('Final gesture end step delayMs must be 0 because there is no next step');
324
298
  }
325
- totalDelayMs += integerInRange(String(step.delayMs), 'gesture delayMs', 0, 5_000);
299
+ totalDelayMs += integerInRange(String(step.delayMs), 'gesture delayMs', LIMITS.gestureDelayMs.min, LIMITS.gestureDelayMs.max);
326
300
  }
327
301
  }
328
302
  if (totalDelayMs > timeoutMs)
@@ -332,12 +306,12 @@ function assertInteraction(interaction, timeoutMs) {
332
306
  case 'getClipboard':
333
307
  return;
334
308
  case 'setClipboard':
335
- if (interaction.text.length > 100_000)
336
- throw new Error('clipboard text must contain at most 100000 UTF-16 code units');
309
+ if (interaction.text.length > LIMITS.clipboardTextLength.max)
310
+ throw new Error(`clipboard text must contain at most ${LIMITS.clipboardTextLength.max} UTF-16 code units`);
337
311
  return;
338
312
  case 'typeText':
339
- if (interaction.text.length < 1 || interaction.text.length > 10_000) {
340
- throw new Error('text must contain from 1 to 10000 characters');
313
+ if (interaction.text.length < LIMITS.typeTextLength.min || interaction.text.length > LIMITS.typeTextLength.max) {
314
+ throw new Error(`text must contain from ${LIMITS.typeTextLength.min} to ${LIMITS.typeTextLength.max} characters`);
341
315
  }
342
316
  if (!isUsAsciiText(interaction.text)) {
343
317
  throw new Error('text must contain only US ASCII characters, tabs, and line feeds');
@@ -346,7 +320,7 @@ function assertInteraction(interaction, timeoutMs) {
346
320
  case 'pressKey':
347
321
  case 'pressButton':
348
322
  if (interaction.durationMs !== undefined) {
349
- integerInRange(String(interaction.durationMs), '--duration', 20, 30_000);
323
+ integerInRange(String(interaction.durationMs), '--duration', LIMITS.pressDurationMs.min, LIMITS.pressDurationMs.max);
350
324
  }
351
325
  return;
352
326
  case 'scroll':
@@ -395,7 +369,7 @@ export function parseSimulatorGestureSteps(raw, timeoutMs = DEFAULT_INTERACTION_
395
369
  : [points[0], points[1]];
396
370
  const delayMs = record.delayMs === undefined
397
371
  ? undefined
398
- : integerInRange(String(record.delayMs), `gesture step ${index} delayMs`, 0, 5_000);
372
+ : integerInRange(String(record.delayMs), `gesture step ${index} delayMs`, LIMITS.gestureDelayMs.min, LIMITS.gestureDelayMs.max);
399
373
  return {
400
374
  phase: record.phase,
401
375
  points: tuple,
@@ -406,7 +380,7 @@ export function parseSimulatorGestureSteps(raw, timeoutMs = DEFAULT_INTERACTION_
406
380
  return steps;
407
381
  }
408
382
  function interactionTimeout(opts) {
409
- return integerInRange(opts.timeout, '--timeout', 100, 60_000, DEFAULT_INTERACTION_TIMEOUT_MS);
383
+ return integerInRange(opts.timeout, '--timeout', LIMITS.timeoutMs.min, LIMITS.timeoutMs.max, DEFAULT_INTERACTION_TIMEOUT_MS);
410
384
  }
411
385
  function interactionRequestId(opts) {
412
386
  const requestId = opts.requestId?.trim() || `cli_${randomUUID()}`;
@@ -463,7 +437,7 @@ async function withInteractionCancellation(timeoutMs, requestId, actionName, ses
463
437
  }
464
438
  function addInteractionOptions(command) {
465
439
  return command
466
- .option('--timeout <milliseconds>', 'acknowledgement timeout in milliseconds (100-60000)', String(DEFAULT_INTERACTION_TIMEOUT_MS))
440
+ .option('--timeout <milliseconds>', `acknowledgement timeout in milliseconds (${LIMITS.timeoutMs.min}-${LIMITS.timeoutMs.max})`, String(DEFAULT_INTERACTION_TIMEOUT_MS))
467
441
  .option('--request-id <id>', 'caller-supplied correlation id')
468
442
  .option('--json', 'output a stable JSON result or error envelope', false);
469
443
  }
@@ -1220,13 +1194,13 @@ function registerSimulatorCommands(program, platform) {
1220
1194
  .argument('<from-y>', 'start y from 0 to 1')
1221
1195
  .argument('<to-x>', 'end x from 0 to 1')
1222
1196
  .argument('<to-y>', 'end y from 0 to 1')
1223
- .option('--duration <milliseconds>', 'swipe duration in milliseconds (50-30000)')).action((id, fromX, fromY, toX, toY, opts) => action(() => runSimulatorInteraction(platform, id, {
1197
+ .option('--duration <milliseconds>', `swipe duration in milliseconds (${LIMITS.swipeDurationMs.min}-${LIMITS.swipeDurationMs.max})`)).action((id, fromX, fromY, toX, toY, opts) => action(() => runSimulatorInteraction(platform, id, {
1224
1198
  action: 'swipe',
1225
1199
  from: normalizedPoint(fromX, fromY, 'swipe start'),
1226
1200
  to: normalizedPoint(toX, toY, 'swipe end'),
1227
1201
  ...(opts.duration === undefined
1228
1202
  ? {}
1229
- : { durationMs: integerInRange(opts.duration, '--duration', 50, 30_000) }),
1203
+ : { durationMs: integerInRange(opts.duration, '--duration', LIMITS.swipeDurationMs.min, LIMITS.swipeDurationMs.max) }),
1230
1204
  }, opts), opts));
1231
1205
  addInteractionOptions(simulator
1232
1206
  .command('gesture')
@@ -1247,27 +1221,26 @@ function registerSimulatorCommands(program, platform) {
1247
1221
  .command('type-text')
1248
1222
  .description(`Type US ASCII text into ${article} ${label} session`)
1249
1223
  .argument('<id>', 'session id')
1250
- .argument('<text>', '1-10000 US ASCII characters; quote text containing spaces')).action((id, text, opts) => action(() => runSimulatorInteraction(platform, id, { action: 'typeText', text }, opts), opts));
1224
+ .argument('<text>', `${LIMITS.typeTextLength.min}-${LIMITS.typeTextLength.max} US ASCII characters; quote text containing spaces`)).action((id, text, opts) => action(() => runSimulatorInteraction(platform, id, { action: 'typeText', text }, opts), opts));
1251
1225
  addInteractionOptions(simulator
1252
1226
  .command('press-key')
1253
1227
  .description(`Press a semantic keyboard key in ${article} ${label} session`)
1254
1228
  .argument('<id>', 'session id')
1255
1229
  .argument('<key>', 'semantic key, for example a, enter, arrowUp, or f1')
1256
- .option('--duration <milliseconds>', 'key hold duration in milliseconds (20-30000)')
1230
+ .option('--duration <milliseconds>', `key hold duration in milliseconds (${LIMITS.pressDurationMs.min}-${LIMITS.pressDurationMs.max})`)
1257
1231
  .option('--shift', 'hold the left Shift modifier', false)
1258
1232
  .option('--control', 'hold the left Control modifier', false)
1259
1233
  .option('--alt', 'hold the left Alt modifier', false)
1260
1234
  .option('--meta', 'hold the left Meta/Command modifier', false)
1261
1235
  .addHelpText('after', `\nSupported keys:\n ${SIMULATOR_KEYS.join(', ')}\n`)).action((id, rawKey, opts) => action(() => {
1262
- const modifiers = ['shift', 'control', 'alt', 'meta']
1263
- .filter((modifier) => opts[modifier]);
1236
+ const modifiers = SIMULATOR_KEY_MODIFIERS.filter((modifier) => opts[modifier]);
1264
1237
  return runSimulatorInteraction(platform, id, {
1265
1238
  action: 'pressKey',
1266
1239
  key: simulatorKey(rawKey),
1267
1240
  ...(modifiers.length ? { modifiers } : {}),
1268
1241
  ...(opts.duration === undefined
1269
1242
  ? {}
1270
- : { durationMs: integerInRange(opts.duration, '--duration', 20, 30_000) }),
1243
+ : { durationMs: integerInRange(opts.duration, '--duration', LIMITS.pressDurationMs.min, LIMITS.pressDurationMs.max) }),
1271
1244
  }, opts);
1272
1245
  }, opts));
1273
1246
  addInteractionOptions(simulator
@@ -1275,12 +1248,12 @@ function registerSimulatorCommands(program, platform) {
1275
1248
  .description(`Press a simulator hardware or system button in ${article} ${label} session`)
1276
1249
  .argument('<id>', 'session id')
1277
1250
  .argument('<button>', `one of: ${SIMULATOR_BUTTONS.join(', ')}`)
1278
- .option('--duration <milliseconds>', 'button hold duration in milliseconds (20-30000)')).action((id, rawButton, opts) => action(() => runSimulatorInteraction(platform, id, {
1251
+ .option('--duration <milliseconds>', `button hold duration in milliseconds (${LIMITS.pressDurationMs.min}-${LIMITS.pressDurationMs.max})`)).action((id, rawButton, opts) => action(() => runSimulatorInteraction(platform, id, {
1279
1252
  action: 'pressButton',
1280
1253
  button: simulatorButton(rawButton),
1281
1254
  ...(opts.duration === undefined
1282
1255
  ? {}
1283
- : { durationMs: integerInRange(opts.duration, '--duration', 20, 30_000) }),
1256
+ : { durationMs: integerInRange(opts.duration, '--duration', LIMITS.pressDurationMs.min, LIMITS.pressDurationMs.max) }),
1284
1257
  }, opts), opts));
1285
1258
  addInteractionOptions(simulator
1286
1259
  .command('rotate')
@@ -1298,8 +1271,8 @@ function registerSimulatorCommands(program, platform) {
1298
1271
  .command('scroll')
1299
1272
  .description(`Send normalized scroll deltas to ${article} ${label} session`)
1300
1273
  .argument('<id>', 'session id')
1301
- .argument('<delta-x>', 'horizontal delta from -1 to 1')
1302
- .argument('<delta-y>', 'vertical delta from -1 to 1')
1274
+ .argument('<delta-x>', `horizontal delta from ${LIMITS.scrollDelta.min} to ${LIMITS.scrollDelta.max}`)
1275
+ .argument('<delta-y>', `vertical delta from ${LIMITS.scrollDelta.min} to ${LIMITS.scrollDelta.max}`)
1303
1276
  .option('--x <coordinate>', 'normalized anchor x; requires --y')
1304
1277
  .option('--y <coordinate>', 'normalized anchor y; requires --x')).action((id, deltaX, deltaY, opts) => action(() => {
1305
1278
  if ((opts.x === undefined) !== (opts.y === undefined))
@@ -1309,8 +1282,8 @@ function registerSimulatorCommands(program, platform) {
1309
1282
  : undefined;
1310
1283
  return runSimulatorInteraction(platform, id, {
1311
1284
  action: 'scroll',
1312
- deltaX: finiteInRange(deltaX, 'delta-x', -1, 1),
1313
- deltaY: finiteInRange(deltaY, 'delta-y', -1, 1),
1285
+ deltaX: finiteInRange(deltaX, 'delta-x', LIMITS.scrollDelta.min, LIMITS.scrollDelta.max),
1286
+ deltaY: finiteInRange(deltaY, 'delta-y', LIMITS.scrollDelta.min, LIMITS.scrollDelta.max),
1314
1287
  ...(anchor ?? {}),
1315
1288
  }, opts);
1316
1289
  }, opts));
@@ -1326,9 +1299,9 @@ function registerSimulatorCommands(program, platform) {
1326
1299
  .command('rotate-digital-crown')
1327
1300
  .description(`Request Digital Crown input for ${article} ${label} session (unsupported on current mobile sessions)`)
1328
1301
  .argument('<id>', 'session id')
1329
- .argument('<delta>', 'nonzero crown delta from -10000 to 10000')).action((id, delta, opts) => action(() => runSimulatorInteraction(platform, id, {
1302
+ .argument('<delta>', `nonzero crown delta from ${LIMITS.digitalCrownDelta.min} to ${LIMITS.digitalCrownDelta.max}`)).action((id, delta, opts) => action(() => runSimulatorInteraction(platform, id, {
1330
1303
  action: 'rotateDigitalCrown',
1331
- delta: finiteInRange(delta, 'delta', -10_000, 10_000),
1304
+ delta: finiteInRange(delta, 'delta', LIMITS.digitalCrownDelta.min, LIMITS.digitalCrownDelta.max),
1332
1305
  }, opts), opts));
1333
1306
  addInteractionOptions(simulator
1334
1307
  .command('set-render-debug')
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const CLI_VERSION = '0.2.197';
1
+ export const CLI_VERSION = '0.2.198';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runcloud",
3
- "version": "0.2.197",
3
+ "version": "0.2.198",
4
4
  "description": "Create and control run.cloud remote mobile simulators and cloud sandboxes",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -44,6 +44,7 @@
44
44
  "node": ">=20"
45
45
  },
46
46
  "dependencies": {
47
+ "@run-cloud/sdk": "0.48.0",
47
48
  "commander": "^12.1.0",
48
49
  "ignore": "^7.0.5",
49
50
  "tar": "^7.4.3",
Binary file
Binary file