@limrun/api 0.42.2 → 0.43.0

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 (46) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/client.d.mts +2 -2
  3. package/client.d.mts.map +1 -1
  4. package/client.d.ts +2 -2
  5. package/client.d.ts.map +1 -1
  6. package/client.js.map +1 -1
  7. package/client.mjs.map +1 -1
  8. package/exec-client.d.mts +8 -1
  9. package/exec-client.d.mts.map +1 -1
  10. package/exec-client.d.ts +8 -1
  11. package/exec-client.d.ts.map +1 -1
  12. package/exec-client.js +16 -9
  13. package/exec-client.js.map +1 -1
  14. package/exec-client.mjs +16 -9
  15. package/exec-client.mjs.map +1 -1
  16. package/index.d.mts +1 -1
  17. package/index.d.mts.map +1 -1
  18. package/index.d.ts +1 -1
  19. package/index.d.ts.map +1 -1
  20. package/index.js.map +1 -1
  21. package/index.mjs.map +1 -1
  22. package/package.json +1 -1
  23. package/resources/index.d.mts +1 -1
  24. package/resources/index.d.mts.map +1 -1
  25. package/resources/index.d.ts +1 -1
  26. package/resources/index.d.ts.map +1 -1
  27. package/resources/index.js.map +1 -1
  28. package/resources/index.mjs.map +1 -1
  29. package/resources/xcode-instances-helpers.d.mts +13 -0
  30. package/resources/xcode-instances-helpers.d.mts.map +1 -1
  31. package/resources/xcode-instances-helpers.d.ts +13 -0
  32. package/resources/xcode-instances-helpers.d.ts.map +1 -1
  33. package/resources/xcode-instances-helpers.js +19 -0
  34. package/resources/xcode-instances-helpers.js.map +1 -1
  35. package/resources/xcode-instances-helpers.mjs +19 -0
  36. package/resources/xcode-instances-helpers.mjs.map +1 -1
  37. package/src/client.ts +2 -0
  38. package/src/exec-client.ts +24 -10
  39. package/src/index.ts +1 -0
  40. package/src/resources/index.ts +1 -0
  41. package/src/resources/xcode-instances-helpers.ts +36 -0
  42. package/src/version.ts +1 -1
  43. package/version.d.mts +1 -1
  44. package/version.d.ts +1 -1
  45. package/version.js +1 -1
  46. package/version.mjs +1 -1
package/src/client.ts CHANGED
@@ -73,6 +73,7 @@ import {
73
73
  XcodeClient,
74
74
  XcodeProjectConfig,
75
75
  XcodeBuildOptions,
76
+ XcodeRunOptions,
76
77
  ReactNativeBuildConfig,
77
78
  SimulatorAttachResult,
78
79
  SimulatorStatus,
@@ -891,6 +892,7 @@ export declare namespace Limrun {
891
892
  type XcodeClient as XcodeClient,
892
893
  type XcodeProjectConfig as XcodeProjectConfig,
893
894
  type XcodeBuildOptions as XcodeBuildOptions,
895
+ type XcodeRunOptions as XcodeRunOptions,
894
896
  type ReactNativeBuildConfig as ReactNativeBuildConfig,
895
897
  type SimulatorAttachResult as SimulatorAttachResult,
896
898
  type SimulatorStatus as SimulatorStatus,
@@ -12,7 +12,7 @@ import { nodeProxyTransport } from './internal/proxy-transport';
12
12
  // Types
13
13
  // =============================================================================
14
14
 
15
- export type ExecRequest = XcodeBuildExecRequest | GradleBuildExecRequest;
15
+ export type ExecRequest = XcodeBuildExecRequest | GradleBuildExecRequest | RunExecRequest;
16
16
 
17
17
  export type XcodeBuildExecRequest = {
18
18
  command: 'xcodebuild';
@@ -81,6 +81,14 @@ export type GradleBuildExecRequest = {
81
81
  };
82
82
  };
83
83
 
84
+ export type RunExecRequest = {
85
+ command: 'run';
86
+ commandLine: string;
87
+ cwd?: string;
88
+ env?: Record<string, string>;
89
+ timeoutSeconds?: number;
90
+ };
91
+
84
92
  export type ExecOptions = {
85
93
  apiUrl: string;
86
94
  token: string;
@@ -250,7 +258,7 @@ export class ExecChildProcess implements PromiseLike<ExecResult> {
250
258
  this.sseConnection = null;
251
259
  }
252
260
  if (!this.execId) {
253
- this.log('warn', 'Failed to cancel build: execId is not set');
261
+ this.log('warn', 'Failed to cancel execution: execId is not set');
254
262
  return;
255
263
  }
256
264
  try {
@@ -260,9 +268,9 @@ export class ExecChildProcess implements PromiseLike<ExecResult> {
260
268
  Authorization: `Bearer ${this.options.token}`,
261
269
  },
262
270
  });
263
- this.log('info', 'Build cancelled');
271
+ this.log('info', 'Execution cancelled');
264
272
  } catch (err) {
265
- this.log('warn', `Failed to cancel build: ${err}`);
273
+ this.log('warn', `Failed to cancel execution: ${err}`);
266
274
  }
267
275
  }
268
276
 
@@ -275,7 +283,11 @@ export class ExecChildProcess implements PromiseLike<ExecResult> {
275
283
  // spread into ExecResult below so callers can surface the download URL), so
276
284
  // it is stripped from the wire body: the daemon OpenAPI schemas do not
277
285
  // declare it, and sending it would 400 under strict request validation.
278
- const { additionalMetadata: _clientOnly, ...wireRequest } = request;
286
+ // The 'run' command has no artifact upload and never carries it.
287
+ const wireRequest = { ...request };
288
+ if ('additionalMetadata' in wireRequest) {
289
+ delete wireRequest.additionalMetadata;
290
+ }
279
291
  let execRes: Response;
280
292
  try {
281
293
  execRes = await nodeProxyTransport.fetch(`${apiUrl}/exec`, {
@@ -315,7 +327,7 @@ export class ExecChildProcess implements PromiseLike<ExecResult> {
315
327
 
316
328
  const execData = (await execRes.json()) as { execId: string };
317
329
  this.execId = execData.execId;
318
- log('debug', `Build started: ${this.execId}`);
330
+ log('debug', `Execution started: ${this.execId}`);
319
331
 
320
332
  // 2. Stream logs via SSE and wait for exit code
321
333
  const eventsUrl = `${apiUrl}/exec/${this.execId}/events`;
@@ -326,6 +338,8 @@ export class ExecChildProcess implements PromiseLike<ExecResult> {
326
338
  let timeoutMs = 3600 * 1000;
327
339
  if (request.command === 'xcodebuild' && request.testflight) {
328
340
  timeoutMs += (Math.max(0, request.testflight.waitTimeoutSeconds ?? 120) + 900) * 1000;
341
+ } else if (request.command === 'run') {
342
+ timeoutMs = (Math.max(1, request.timeoutSeconds ?? 3600) + 60) * 1000;
329
343
  }
330
344
  let exitCode: number;
331
345
  let timedOut = false;
@@ -339,7 +353,7 @@ export class ExecChildProcess implements PromiseLike<ExecResult> {
339
353
  ]);
340
354
  } catch {
341
355
  if (this.killed) {
342
- log('debug', 'Build killed');
356
+ log('debug', 'Execution killed');
343
357
  exitCode = -1;
344
358
  } else {
345
359
  // The client stopped waiting; the remote build may still be running.
@@ -376,12 +390,12 @@ export class ExecChildProcess implements PromiseLike<ExecResult> {
376
390
  exitCode,
377
391
  execId: this.execId!,
378
392
  status,
379
- ...(request.additionalMetadata ?? {}),
393
+ ...('additionalMetadata' in request ? request.additionalMetadata ?? {} : {}),
380
394
  ...(this.testflightEvent ? { testflight: this.testflightEvent } : {}),
381
395
  ...(timedOut ? { timedOut } : {}),
382
396
  };
383
397
 
384
- this.log('debug', `Build finished: ${result.status} (exit ${result.exitCode})`);
398
+ this.log('debug', `Execution finished: ${result.status} (exit ${result.exitCode})`);
385
399
  return result;
386
400
  }
387
401
 
@@ -426,7 +440,7 @@ export class ExecChildProcess implements PromiseLike<ExecResult> {
426
440
  this.log('warn', `SSE exitCode event has invalid data: ${data}`);
427
441
  return;
428
442
  }
429
- this.log('debug', `Build completed via SSE: exitCode=${exitCode}`);
443
+ this.log('debug', `Execution completed via SSE: exitCode=${exitCode}`);
430
444
  resolve(exitCode);
431
445
  }
432
446
  },
package/src/index.ts CHANGED
@@ -41,6 +41,7 @@ export {
41
41
  DEFAULT_RBE_TUNNEL_PORT,
42
42
  type XcodeProjectConfig,
43
43
  type XcodeBuildOptions,
44
+ type XcodeRunOptions,
44
45
  type XcodeGenConfig,
45
46
  type ReactNativeBuildConfig,
46
47
  type SimulatorAttachResult,
@@ -53,6 +53,7 @@ export {
53
53
  type XcodeClient,
54
54
  type XcodeProjectConfig,
55
55
  type XcodeBuildOptions,
56
+ type XcodeRunOptions,
56
57
  type XcodeGenConfig,
57
58
  type ReactNativeBuildConfig,
58
59
  type SimulatorAttachResult,
@@ -68,6 +68,14 @@ export type SyncOptions = {
68
68
  onSyncComplete?: FolderSyncOptions['onSyncComplete'];
69
69
  };
70
70
 
71
+ export type XcodeRunOptions = {
72
+ /** Working directory relative to the synced workspace root. Defaults to ".". */
73
+ cwd?: string;
74
+ /** Environment variables to add to limbuild's curated sandbox environment. */
75
+ env?: Record<string, string>;
76
+ /** Server-side timeout in seconds. Defaults to 3600; maximum 21600. */
77
+ timeoutSeconds?: number;
78
+ };
71
79
  export type XcodeProjectConfig = {
72
80
  workspace?: string;
73
81
  project?: string;
@@ -318,6 +326,12 @@ export type XcodeClient = {
318
326
  */
319
327
  xcodebuild: (settings?: XcodeProjectConfig, options?: XcodeBuildOptions) => ExecChildProcess;
320
328
 
329
+ /**
330
+ * Run a one-shot shell command in the synced workspace.
331
+ * Output and the remote exit code are streamed through the returned process.
332
+ */
333
+ run: (commandLine: string, options?: XcodeRunOptions) => ExecChildProcess;
334
+
321
335
  /**
322
336
  * Attach a simulator to this xcode instance.
323
337
  * After attaching, the latest installable build is installed on the simulator:
@@ -727,6 +741,28 @@ export class XcodeInstances extends GeneratedXcodeInstances {
727
741
  return exec(request, { apiUrl, token, log });
728
742
  },
729
743
 
744
+ run(commandLine: string, options?: XcodeRunOptions): ExecChildProcess {
745
+ if (commandLine.trim() === '') {
746
+ throw new Error('commandLine must not be empty');
747
+ }
748
+ if (
749
+ options?.timeoutSeconds !== undefined &&
750
+ (!Number.isInteger(options.timeoutSeconds) ||
751
+ options.timeoutSeconds < 1 ||
752
+ options.timeoutSeconds > 21600)
753
+ ) {
754
+ throw new Error('timeoutSeconds must be an integer between 1 and 21600');
755
+ }
756
+ const request: ExecRequest = {
757
+ command: 'run',
758
+ commandLine,
759
+ cwd: options?.cwd ?? '.',
760
+ ...(options?.env && { env: options.env }),
761
+ ...(options?.timeoutSeconds !== undefined && { timeoutSeconds: options.timeoutSeconds }),
762
+ };
763
+ return exec(request, { apiUrl, token, log });
764
+ },
765
+
730
766
  async getSimulator(): Promise<SimulatorStatus> {
731
767
  const res = await nodeProxyTransport.fetch(`${apiUrl}/simulator`, {
732
768
  method: 'GET',
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = '0.42.2'; // x-release-please-version
1
+ export const VERSION = '0.43.0'; // x-release-please-version
package/version.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.42.2";
1
+ export declare const VERSION = "0.43.0";
2
2
  //# sourceMappingURL=version.d.mts.map
package/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.42.2";
1
+ export declare const VERSION = "0.43.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = '0.42.2'; // x-release-please-version
4
+ exports.VERSION = '0.43.0'; // x-release-please-version
5
5
  //# sourceMappingURL=version.js.map
package/version.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '0.42.2'; // x-release-please-version
1
+ export const VERSION = '0.43.0'; // x-release-please-version
2
2
  //# sourceMappingURL=version.mjs.map