@newly/cli 0.1.126 → 0.1.130

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.
@@ -80,8 +80,8 @@ runcloud ios logs <id> --tail 200 # read logs from this
80
80
  runcloud ios logs <id> --follow # follow new log entries
81
81
  runcloud ios delete <id> # release the session
82
82
 
83
- # Android works the same under `runcloud android …`
84
- runcloud android create --model pixel
83
+ # Android also requires the Expo SDK profile used by the app; pools never substitute.
84
+ runcloud android create --model pixel --expo-sdk-profile expo-57
85
85
  runcloud android swipe <id> 0.5 0.8 0.5 0.2 --duration 250
86
86
  runcloud android press-key <id> enter
87
87
  runcloud android accessibility-tree <id> --json
@@ -90,6 +90,12 @@ runcloud android mic inject <id> ./tone.wav --bundle-id com.example.Recorder
90
90
  runcloud android screenshot <id> --output android.png --json
91
91
  ```
92
92
 
93
+ Use `--expo-sdk-profile expo-54` for Expo 54 projects and `expo-57` for Expo 57
94
+ projects. `create`, `get`, `list`, and `mobile launch --json` expose the selected
95
+ profile and immutable Expo Go APK, emulator image, toolchain, and profile
96
+ digests. If that profile is full, the command returns
97
+ `expo_profile_capacity_unavailable`; it does not lease the other pool.
98
+
93
99
  `open-url` accepts HTTPS URLs and application deep links on both platforms. Keep
94
100
  the complete target quoted so its URI delimiters stay in one argument:
95
101
 
@@ -279,9 +285,11 @@ runcloud sandbox create --no-secrets # state explicitly t
279
285
  `--secret-group`, `--secret`, and `--env` are repeatable and **order matters** —
280
286
  a later one wins a name collision, and `--env` is applied last.
281
287
 
282
- `runcloud sandbox secrets <id>` re-attaches on a running sandbox. It *replaces*
283
- the whole set rather than merging, which is how a credential gets revoked:
284
- passing no flags at all takes them all back.
288
+ `runcloud sandbox secrets set <id>` re-attaches on a running sandbox. It
289
+ *replaces* the whole set rather than merging. Use
290
+ `runcloud sandbox secrets revoke <id>` to take everything back; the bare
291
+ `runcloud sandbox secrets <id>` form only shows the last recorded delivery
292
+ inventory, not proof of the live guest state.
285
293
 
286
294
  A value can never be passed as a command argument — it would land in your shell
287
295
  history, in `ps` output, and in CI logs. Use a hidden prompt, a file, or stdin.
@@ -298,8 +306,8 @@ runcloud image refresh python:3.12-slim # re-pin the tag to its current u
298
306
  runcloud sandbox create --image python:3.12-slim
299
307
  ```
300
308
 
301
- Built in: `runcloud/agent-base` (the default), `runcloud/desktop`, and
302
- `runcloud/box` (the default with `--expose`).
309
+ Built in: `runcloud/agent-base` (the default, including with `--expose`),
310
+ `runcloud/desktop`, and `newly/postgres`.
303
311
 
304
312
  ## Demos
305
313
 
@@ -944,6 +944,7 @@ async function createSimulatorSession(platform, opts) {
944
944
  .filter((id) => typeof id === 'string' && id.length > 0),
945
945
  ];
946
946
  return await client().post(`/run-cloud/${platform}`, {
947
+ ...(platform === 'android' ? { expoSdkProfile: opts.expoSdkProfile } : {}),
947
948
  ...(opts.orgId ? { orgId: opts.orgId } : {}),
948
949
  model: opts.model,
949
950
  region: opts.region,
@@ -1018,7 +1019,7 @@ function registerSimulatorCommands(program, platform) {
1018
1019
  const simulator = program
1019
1020
  .command(platform)
1020
1021
  .description(`Create, inspect, interact with, capture, and release ${label} sessions`);
1021
- simulator
1022
+ const createCommand = simulator
1022
1023
  .command('create')
1023
1024
  .description(`Create a remote ${label} session`)
1024
1025
  .option('--model <model>', platform === 'ios' ? 'simulator model' : 'emulator model', platform === 'ios' ? 'iphone' : 'pixel')
@@ -1033,7 +1034,11 @@ function registerSimulatorCommands(program, platform) {
1033
1034
  .option('--codec <auto|mjpeg|webrtc>', 'force the simulator viewer stream codec', 'auto')
1034
1035
  .option('--rm', 'release the session when this command exits', false)
1035
1036
  .option('--json', 'output JSON', false)
1036
- .addOption(new Option('--dev-host <host>', 'dev-only: target a specific simulator fleet host').hideHelp())
1037
+ .addOption(new Option('--dev-host <host>', 'dev-only: target a specific simulator fleet host').hideHelp());
1038
+ if (platform === 'android') {
1039
+ createCommand.addOption(new Option('--expo-sdk-profile <profile>', 'required immutable Expo SDK capacity profile').choices(['expo-54', 'expo-57']).makeOptionMandatory());
1040
+ }
1041
+ createCommand
1037
1042
  .action((opts) => action(async () => {
1038
1043
  print(await createSimulatorSession(platform, opts), opts);
1039
1044
  }, opts));
@@ -1614,6 +1619,7 @@ export function registerRunCloud(program) {
1614
1619
  .option('--inactivity-timeout <duration>', 'idle timeout such as 60s, 3m, or none')
1615
1620
  .option('--hard-timeout <duration>', 'maximum lifetime such as 10m or 1h')
1616
1621
  .option('--codec <auto|mjpeg|webrtc>', 'viewer codec', 'auto')
1622
+ .addOption(new Option('--expo-sdk-profile <profile>', 'required for Android: immutable Expo SDK capacity profile').choices(['expo-54', 'expo-57']))
1617
1623
  .option('--json', 'output JSON', false)
1618
1624
  .action((opts) => action(async () => {
1619
1625
  if (Boolean(opts.asset) === Boolean(opts.build)) {
@@ -1622,11 +1628,18 @@ export function registerRunCloud(program) {
1622
1628
  if (opts.platform !== 'ios' && opts.platform !== 'android') {
1623
1629
  throw new Error('--platform must be ios or android');
1624
1630
  }
1631
+ if (opts.platform === 'android' && !opts.expoSdkProfile) {
1632
+ throw new Error('--expo-sdk-profile is required when --platform android');
1633
+ }
1634
+ if (opts.platform === 'ios' && opts.expoSdkProfile) {
1635
+ throw new Error('--expo-sdk-profile is supported only when --platform android');
1636
+ }
1625
1637
  print(await client().postWithHeaders('/run-cloud/mobile/launch', {
1626
1638
  ...(opts.asset ? { assetId: opts.asset } : { buildId: opts.build }),
1627
1639
  platform: opts.platform,
1628
1640
  ...(opts.orgId ? { orgId: opts.orgId } : {}),
1629
1641
  session: {
1642
+ ...(opts.platform === 'android' ? { expoSdkProfile: opts.expoSdkProfile } : {}),
1630
1643
  ...(opts.model ? { model: opts.model } : {}),
1631
1644
  ...(opts.region ? { region: opts.region } : {}),
1632
1645
  ...(opts.displayName ? { displayName: opts.displayName } : {}),
@@ -1636,7 +1649,7 @@ export function registerRunCloud(program) {
1636
1649
  ...(opts.codec ? { codec: opts.codec } : {}),
1637
1650
  },
1638
1651
  }, { 'Idempotency-Key': opts.idempotencyKey }), opts);
1639
- }));
1652
+ }, opts));
1640
1653
  mobile
1641
1654
  .command('get')
1642
1655
  .description('Read one mobile launch operation and its session or failure')
@@ -314,7 +314,7 @@ export function registerSandbox(program) {
314
314
  withOutput(sandbox
315
315
  .command('create')
316
316
  .description('Spawn a microVM sandbox')
317
- .option('--image <ref>', 'base image (default runcloud/agent-base, or runcloud/box with --expose)')
317
+ .option('--image <ref>', 'base image (default runcloud/agent-base)')
318
318
  .option('--region <region>', 'placement region')
319
319
  .option('--name <name>', 'human-readable name; with --expose, the hostname prefix <name>-box.run.cloud')
320
320
  .option('--org <id>', 'billing and ownership organization')
@@ -339,7 +339,7 @@ export function registerSandbox(program) {
339
339
  throw new Error('--persistent and --expose keep the sandbox running; drop the non-zero --idle-pause');
340
340
  }
341
341
  const body = {
342
- image: opts.image ?? (exposed ? 'runcloud/box' : 'runcloud/agent-base'),
342
+ image: opts.image ?? 'runcloud/agent-base',
343
343
  };
344
344
  if (opts.name)
345
345
  body.name = opts.name;
@@ -810,7 +810,7 @@ export function registerSandbox(program) {
810
810
  .argument('<name>', 'hostname prefix: <name>-box.run.cloud')
811
811
  .option('--sandbox <id>', 'attach an existing sandbox created with --idle-pause 0')
812
812
  .option('--port <port>', 'guest port to publish', parsePort, 3000)
813
- .option('--image <ref>', 'base image for a new sandbox (runcloud/box or runcloud/box-agent)', 'runcloud/box')
813
+ .option('--image <ref>', 'base image for a new sandbox', 'runcloud/agent-base')
814
814
  .option('--region <region>', 'placement region for a new sandbox')
815
815
  .option('--org <id>', 'billing and ownership organization for a new sandbox')
816
816
  .option('--cpu <cores>', 'vCPU allocation for a new box', parseCpuCores, DEFAULT_BOX_CPU_CORES)
@@ -35,6 +35,12 @@ function hostname(record) {
35
35
  const port = record.exposedPort ?? record.box?.port;
36
36
  return host && port ? `${host}:${port}` : host;
37
37
  }
38
+ function tags(record) {
39
+ const entries = Object.entries(record.tags ?? {}).sort(([left], [right]) => left.localeCompare(right));
40
+ return entries.length > 0
41
+ ? entries.map(([key, value]) => `${key}=${value}`).join('\n')
42
+ : undefined;
43
+ }
38
44
  function title(record, verb) {
39
45
  if (verb === 'details')
40
46
  return 'Sandbox';
@@ -62,6 +68,7 @@ export function renderSandbox(record, verb = 'details') {
62
68
  { label: 'Idle pause', value: formatSeconds(record.idle_pause_seconds) },
63
69
  { label: 'Timeout', value: formatSeconds(record.timeout_seconds) },
64
70
  { label: 'Hostname', value: hostname(record) },
71
+ { label: 'Tags', value: tags(record) },
65
72
  { label: 'Image digest', value: shortDigest(record.image_digest) },
66
73
  { label: 'Created', value: formatAge(record.created_at) },
67
74
  { label: 'Last active', value: verb === 'details' ? formatAge(record.last_active_at) : undefined },
package/dist/config.js CHANGED
@@ -12,7 +12,10 @@ export function sanitizeAccount(value) {
12
12
  }
13
13
  export function isRunCloud() {
14
14
  const names = [process.argv[1], process.execPath].map((path) => basename(path ?? ''));
15
- return names.some((name) => name === 'runcloud' || name === 'run-cloud' || name === 'run-cloud.js');
15
+ return names.some((name) => name === 'runcloud'
16
+ || name === 'run-cloud'
17
+ || name === 'run-cloud.js'
18
+ || name === 'run-cloud.ts');
16
19
  }
17
20
  function credentialsHome() {
18
21
  if (isRunCloud())
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const CLI_VERSION = '0.1.126';
1
+ export const CLI_VERSION = '0.1.130';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newly/cli",
3
- "version": "0.1.126",
3
+ "version": "0.1.130",
4
4
  "description": "Develop, provision, and deploy Newly backends from your terminal",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",