@limrun/api 0.24.0 → 0.24.2

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 (80) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/client.d.mts +3 -2
  3. package/client.d.mts.map +1 -1
  4. package/client.d.ts +3 -2
  5. package/client.d.ts.map +1 -1
  6. package/client.js +2 -2
  7. package/client.js.map +1 -1
  8. package/client.mjs +1 -1
  9. package/client.mjs.map +1 -1
  10. package/exec-client.d.mts +3 -2
  11. package/exec-client.d.mts.map +1 -1
  12. package/exec-client.d.ts +3 -2
  13. package/exec-client.d.ts.map +1 -1
  14. package/exec-client.js +6 -1
  15. package/exec-client.js.map +1 -1
  16. package/exec-client.mjs +6 -1
  17. package/exec-client.mjs.map +1 -1
  18. package/index.d.mts +1 -1
  19. package/index.d.mts.map +1 -1
  20. package/index.d.ts +1 -1
  21. package/index.d.ts.map +1 -1
  22. package/index.js +1 -3
  23. package/index.js.map +1 -1
  24. package/index.mjs +0 -1
  25. package/index.mjs.map +1 -1
  26. package/instance-client.d.mts +13 -1
  27. package/instance-client.d.mts.map +1 -1
  28. package/instance-client.d.ts +13 -1
  29. package/instance-client.d.ts.map +1 -1
  30. package/instance-client.js +21 -2
  31. package/instance-client.js.map +1 -1
  32. package/instance-client.mjs +20 -2
  33. package/instance-client.mjs.map +1 -1
  34. package/internal/tslib.js +4 -4
  35. package/ios-client.d.mts +14 -2
  36. package/ios-client.d.mts.map +1 -1
  37. package/ios-client.d.ts +14 -2
  38. package/ios-client.d.ts.map +1 -1
  39. package/ios-client.js +24 -44
  40. package/ios-client.js.map +1 -1
  41. package/ios-client.mjs +23 -43
  42. package/ios-client.mjs.map +1 -1
  43. package/package.json +1 -11
  44. package/resources/index.d.mts +2 -1
  45. package/resources/index.d.mts.map +1 -1
  46. package/resources/index.d.ts +2 -1
  47. package/resources/index.d.ts.map +1 -1
  48. package/resources/index.js +3 -3
  49. package/resources/index.js.map +1 -1
  50. package/resources/index.mjs +1 -1
  51. package/resources/index.mjs.map +1 -1
  52. package/resources/xcode-instances-helpers.d.mts +76 -0
  53. package/resources/xcode-instances-helpers.d.mts.map +1 -0
  54. package/resources/xcode-instances-helpers.d.ts +76 -0
  55. package/resources/xcode-instances-helpers.d.ts.map +1 -0
  56. package/resources/xcode-instances-helpers.js +150 -0
  57. package/resources/xcode-instances-helpers.js.map +1 -0
  58. package/resources/xcode-instances-helpers.mjs +145 -0
  59. package/resources/xcode-instances-helpers.mjs.map +1 -0
  60. package/src/client.ts +11 -1
  61. package/src/exec-client.ts +8 -3
  62. package/src/index.ts +6 -9
  63. package/src/instance-client.ts +25 -4
  64. package/src/ios-client.ts +27 -44
  65. package/src/resources/index.ts +7 -1
  66. package/src/resources/xcode-instances-helpers.ts +228 -0
  67. package/src/version.ts +1 -1
  68. package/version.d.mts +1 -1
  69. package/version.d.ts +1 -1
  70. package/version.js +1 -1
  71. package/version.mjs +1 -1
  72. package/sandbox-client.d.mts +0 -129
  73. package/sandbox-client.d.mts.map +0 -1
  74. package/sandbox-client.d.ts +0 -129
  75. package/sandbox-client.d.ts.map +0 -1
  76. package/sandbox-client.js +0 -159
  77. package/sandbox-client.js.map +0 -1
  78. package/sandbox-client.mjs +0 -155
  79. package/sandbox-client.mjs.map +0 -1
  80. package/src/sandbox-client.ts +0 -278
package/src/ios-client.ts CHANGED
@@ -20,17 +20,10 @@ export type ConnectionState = 'connecting' | 'connected' | 'disconnected' | 'rec
20
20
  */
21
21
  export type ConnectionStateCallback = (state: ConnectionState) => void;
22
22
 
23
- function generateRecordingFilename(): string {
24
- const rand = Math.random().toString(36).slice(2, 5).padEnd(3, '0');
25
- const now = new Date();
26
- const formattedDate = now.toISOString().replace(/[-:]/g, '_').replace('T', '_').replace(/\..+/, '');
23
+ const ACTIVE_RECORDING_FILENAME = 'recording.mp4';
27
24
 
28
- // Example: 20240602_17_45_30 for June 2, 2024 17:45:30 UTC
29
- return `ios_video_${formattedDate}_${rand}.mp4`;
30
- }
31
-
32
- function buildDownloadUrl(apiUrl: string, filename: string): string {
33
- return `${apiUrl}/files?name=${encodeURIComponent(filename)}`;
25
+ function buildDownloadUrl(apiUrl: string): string {
26
+ return `${apiUrl}/files?name=${encodeURIComponent(ACTIVE_RECORDING_FILENAME)}`;
34
27
  }
35
28
 
36
29
  /**
@@ -316,11 +309,13 @@ export type InstanceClient = {
316
309
 
317
310
  /**
318
311
  * Start recording simulator video. Use stopRecording() to stop the recording.
312
+ * When provided, `quality` must be one of `5`, `6`, `7`, `8`, `9`, or `10`.
313
+ * The server default is `5`.
319
314
  */
320
- startRecording: () => Promise<void>;
315
+ startRecording: (options?: { quality?: RecordingQuality }) => Promise<void>;
321
316
 
322
317
  /**
323
- * Stop the active recording for this client instance.
318
+ * Stop the active server-side recording.
324
319
  * If `saveTo.presignedUrl` is provided, the server uploads the completed file there before resolving.
325
320
  * If `saveTo.localPath` is provided, the client downloads the completed file to that path.
326
321
  * If both are provided, both are performed.
@@ -485,6 +480,15 @@ export type InstanceClient = {
485
480
  */
486
481
  export type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'debug';
487
482
 
483
+ export enum RecordingQuality {
484
+ Q5 = 5,
485
+ Q6 = 6,
486
+ Q7 = 7,
487
+ Q8 = 8,
488
+ Q9 = 9,
489
+ Q10 = 10,
490
+ }
491
+
488
492
  /**
489
493
  * Configuration options for creating an iOS client
490
494
  */
@@ -894,8 +898,6 @@ export async function createInstanceClient(options: InstanceClientOptions): Prom
894
898
  let reconnectTimeout: NodeJS.Timeout | undefined;
895
899
  let intentionalDisconnect = false;
896
900
  let lastError: string | undefined;
897
- let activeRecordingFilename: string | undefined;
898
-
899
901
  // Centralized pending requests map - handles all request/response patterns
900
902
  const pendingRequests: Map<string, PendingRequest<any>> = new Map();
901
903
 
@@ -1074,9 +1076,7 @@ export async function createInstanceClient(options: InstanceClientOptions): Prom
1074
1076
  bundleId: msg.bundleId || '',
1075
1077
  }),
1076
1078
  startVideoRecordingResult: () => undefined,
1077
- stopVideoRecordingResult: (msg) => ({
1078
- filename: msg.filename || '',
1079
- }),
1079
+ stopVideoRecordingResult: () => undefined,
1080
1080
  setOrientationResult: () => undefined,
1081
1081
  scrollResult: () => undefined,
1082
1082
  xcrunResult: (msg): CommandResult => ({
@@ -1393,41 +1393,24 @@ export async function createInstanceClient(options: InstanceClientOptions): Prom
1393
1393
  });
1394
1394
  };
1395
1395
 
1396
- const startRecording = async (): Promise<void> => {
1397
- if (activeRecordingFilename) {
1398
- throw new Error(`A recording is already active for this client: ${activeRecordingFilename}`);
1399
- }
1400
- const finalFilename = generateRecordingFilename();
1401
- activeRecordingFilename = finalFilename;
1402
- try {
1403
- await sendRequest<void>('startVideoRecording', { filename: finalFilename });
1404
- } catch (error) {
1405
- if (activeRecordingFilename === finalFilename) {
1406
- activeRecordingFilename = undefined;
1396
+ const startRecording = async (opts?: { quality?: RecordingQuality }): Promise<void> => {
1397
+ const request: { quality?: RecordingQuality } = {};
1398
+ if (opts?.quality !== undefined) {
1399
+ if (!Number.isInteger(opts.quality) || opts.quality < 5 || opts.quality > 10) {
1400
+ throw new Error('quality must be one of: 5, 6, 7, 8, 9, 10');
1407
1401
  }
1408
- throw error;
1402
+ request.quality = opts.quality;
1409
1403
  }
1404
+ await sendRequest<void>('startVideoRecording', request);
1410
1405
  };
1411
1406
 
1412
1407
  const stopRecording = async (saveTo: { presignedUrl?: string; localPath?: string }): Promise<string> => {
1413
- const filename = activeRecordingFilename;
1414
- if (!filename) {
1415
- throw new Error('No active recording for this client. Call startRecording() first.');
1416
- }
1417
- const result = await sendRequest<{ filename: string }>('stopVideoRecording', {
1418
- filename,
1408
+ await sendRequest<void>('stopVideoRecording', {
1419
1409
  upload: saveTo.presignedUrl ? { presignedUrl: saveTo.presignedUrl } : undefined,
1420
1410
  });
1421
- const finalFilename = result.filename || filename;
1422
- const downloadUrl = buildDownloadUrl(options.apiUrl, finalFilename);
1411
+ const downloadUrl = buildDownloadUrl(options.apiUrl);
1423
1412
  if (saveTo.localPath) {
1424
- try {
1425
- await downloadFileToLocalPath(downloadUrl, options.token, saveTo.localPath);
1426
- } finally {
1427
- activeRecordingFilename = undefined;
1428
- }
1429
- } else {
1430
- activeRecordingFilename = undefined;
1413
+ await downloadFileToLocalPath(downloadUrl, options.token, saveTo.localPath);
1431
1414
  }
1432
1415
  return downloadUrl;
1433
1416
  };
@@ -23,7 +23,6 @@ export {
23
23
  type IosInstancesItems,
24
24
  } from './ios-instances';
25
25
  export {
26
- XcodeInstances,
27
26
  type XcodeInstance,
28
27
  type XcodeInstanceCreateParams,
29
28
  type XcodeInstanceListParams,
@@ -31,3 +30,10 @@ export {
31
30
  } from './xcode-instances';
32
31
 
33
32
  export { Assets, AssetGetOrUploadParams, AssetGetOrUploadResponse } from './assets-helpers';
33
+ export {
34
+ XcodeInstances,
35
+ type XcodeCreateClientParams,
36
+ type XcodeClient,
37
+ type XcodeProjectConfig,
38
+ type XcodeBuildOptions,
39
+ } from './xcode-instances-helpers';
@@ -0,0 +1,228 @@
1
+ import os from 'os';
2
+ import path from 'path';
3
+ import crypto from 'crypto';
4
+
5
+ import { XcodeInstances as GeneratedXcodeInstances, type XcodeInstance } from './xcode-instances';
6
+ import { type IosInstance } from './ios-instances';
7
+ import { exec, type ExecChildProcess, type ExecRequest } from '../exec-client';
8
+ import { syncFolder as syncFolderImpl, type FolderSyncOptions } from '../folder-sync';
9
+ import { createIgnoreFn } from '../folder-sync-ignore';
10
+ import { nodeProxyTransport } from '../internal/proxy-transport';
11
+
12
+ export type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'debug';
13
+
14
+ export type SyncOptions = {
15
+ /**
16
+ * If true, watch the folder and re-sync on any changes. Defaults to true.
17
+ */
18
+ watch?: boolean;
19
+ /**
20
+ * Directory for the client-side folder-sync cache.
21
+ * Defaults to a temporary directory under the OS temp directory.
22
+ */
23
+ basisCacheDir?: string;
24
+ /** Max patch size (bytes) to send as delta before falling back to full upload. */
25
+ maxPatchBytes?: number;
26
+ /** If true, install the app after syncing. Defaults to true. */
27
+ install?: boolean;
28
+ /**
29
+ * Optional predicate for ignoring files and directories during sync.
30
+ * Called with the relative path from the sync root (using forward slashes).
31
+ * For directories, the path ends with '/'.
32
+ * Return true to ignore, false to keep.
33
+ */
34
+ ignore?: (relativePath: string) => boolean;
35
+ };
36
+
37
+ export type SyncResult = {
38
+ /** Present only when watch=true; call to stop watching */
39
+ stopWatching?: () => void;
40
+ };
41
+
42
+ export type XcodeProjectConfig = {
43
+ workspace?: string;
44
+ project?: string;
45
+ scheme?: string;
46
+ };
47
+
48
+ export type XcodeBuildOptions = {
49
+ upload?: { assetName: string };
50
+ };
51
+
52
+ export type XcodeClient = {
53
+ /**
54
+ * Sync source code to the xcode instance. In watch mode, keeps syncing on changes.
55
+ */
56
+ sync: (localCodePath: string, opts?: SyncOptions) => Promise<SyncResult>;
57
+
58
+ /**
59
+ * Trigger xcodebuild on the synced source code.
60
+ * Returns a ChildProcess-like object for streaming output.
61
+ *
62
+ * @example
63
+ * const build = xcode.xcodebuild({ scheme: 'MyApp' });
64
+ * build.stdout.on('data', (line) => console.log(line));
65
+ * const { exitCode } = await build;
66
+ */
67
+ xcodebuild: (settings?: XcodeProjectConfig, options?: XcodeBuildOptions) => ExecChildProcess;
68
+
69
+ /**
70
+ * Attach a simulator to this xcode instance.
71
+ * After attaching, builds will auto-install on the simulator.
72
+ */
73
+ attachSimulator: (simulator: IosInstance | { apiUrl: string; token: string }) => Promise<void>;
74
+ };
75
+
76
+ export type XcodeCreateClientParams =
77
+ | { instance: XcodeInstance; logLevel?: LogLevel }
78
+ | { apiUrl: string; token: string; logLevel?: LogLevel };
79
+
80
+ function createLogger(logLevel: LogLevel) {
81
+ const shouldLog = (level: LogLevel) => {
82
+ const levels: LogLevel[] = ['none', 'error', 'warn', 'info', 'debug'];
83
+ return levels.indexOf(logLevel) >= levels.indexOf(level);
84
+ };
85
+ return (level: 'debug' | 'info' | 'warn' | 'error', msg: string) => {
86
+ if (!shouldLog(level)) return;
87
+ const prefix = '[XcodeInstance]';
88
+ if (level === 'error' || level === 'warn') {
89
+ console[level](prefix, msg);
90
+ } else {
91
+ console.log(prefix, msg);
92
+ }
93
+ };
94
+ }
95
+
96
+ export class XcodeInstances extends GeneratedXcodeInstances {
97
+ async createClient(params: XcodeCreateClientParams): Promise<XcodeClient> {
98
+ let apiUrl: string;
99
+ let token: string;
100
+ if ('instance' in params) {
101
+ if (!params.instance.status.apiUrl) {
102
+ throw new Error('Instance not ready: apiUrl is not available');
103
+ }
104
+ apiUrl = params.instance.status.apiUrl;
105
+ token = params.instance.status.token;
106
+ } else {
107
+ apiUrl = params.apiUrl;
108
+ token = params.token;
109
+ }
110
+
111
+ const log = createLogger(params.logLevel ?? 'info');
112
+ const client = this._client;
113
+
114
+ return {
115
+ async sync(localCodePath: string, opts?: SyncOptions): Promise<SyncResult> {
116
+ const resolvedPath = path.resolve(localCodePath);
117
+ const folderName = path.basename(resolvedPath);
118
+ const hash = crypto.createHash('sha1').update(resolvedPath).digest('hex').slice(0, 8);
119
+ const cacheKey = `limsync-cache-${folderName}-${hash}`;
120
+ const basisCacheDir = opts?.basisCacheDir ?? path.join(os.tmpdir(), cacheKey);
121
+ const codeSyncOpts: FolderSyncOptions = {
122
+ apiUrl,
123
+ token,
124
+ udid: cacheKey,
125
+ install: opts?.install ?? true,
126
+ ignoreFn: await createIgnoreFn(localCodePath, {
127
+ basisCacheDir,
128
+ additional: (relativePath: string) => {
129
+ if (
130
+ relativePath.startsWith('build/') ||
131
+ relativePath.startsWith('.build/') ||
132
+ relativePath.startsWith('DerivedData/') ||
133
+ relativePath.startsWith('Index.noindex/') ||
134
+ relativePath.startsWith('ModuleCache.noindex/') ||
135
+ relativePath.startsWith('.index-build/')
136
+ ) {
137
+ return true;
138
+ }
139
+ if (
140
+ relativePath.startsWith('.swiftpm/') ||
141
+ relativePath.startsWith('Pods/') ||
142
+ relativePath.startsWith('Carthage/Build/')
143
+ ) {
144
+ return true;
145
+ }
146
+ if (relativePath.includes('/xcuserdata/')) {
147
+ return true;
148
+ }
149
+ if (relativePath.includes('.dSYM/')) {
150
+ return true;
151
+ }
152
+ if (opts?.ignore?.(relativePath)) {
153
+ return true;
154
+ }
155
+ return false;
156
+ },
157
+ }),
158
+ basisCacheDir,
159
+ watch: opts?.watch ?? true,
160
+ maxPatchBytes: opts?.maxPatchBytes ?? 4 * 1024 * 1024,
161
+ launchMode: 'ForegroundIfRunning',
162
+ log,
163
+ };
164
+
165
+ const result = await syncFolderImpl(localCodePath, codeSyncOpts);
166
+ if (result.stopWatching) {
167
+ return { stopWatching: result.stopWatching };
168
+ }
169
+ return {};
170
+ },
171
+
172
+ xcodebuild(settings?: XcodeProjectConfig, options?: XcodeBuildOptions): ExecChildProcess {
173
+ const request: ExecRequest = {
174
+ command: 'xcodebuild',
175
+ ...(settings && { xcodebuild: settings }),
176
+ };
177
+
178
+ if (options?.upload) {
179
+ const uploadName = options.upload.assetName;
180
+ const requestPromise = client.assets
181
+ .getOrCreate({ name: uploadName })
182
+ .then((asset) => {
183
+ request.signedUploadUrl = asset.signedUploadUrl;
184
+ return request;
185
+ })
186
+ .catch((err) => {
187
+ throw new Error(
188
+ `Failed to create upload URL for artifact '${uploadName}': ${
189
+ err instanceof Error ? err.message : err
190
+ }`,
191
+ );
192
+ });
193
+ return exec(requestPromise, { apiUrl, token, log });
194
+ }
195
+
196
+ return exec(request, { apiUrl, token, log });
197
+ },
198
+
199
+ async attachSimulator(simulator: IosInstance | { apiUrl: string; token: string }): Promise<void> {
200
+ let simApiUrl: string;
201
+ let simToken: string;
202
+ if ('status' in simulator) {
203
+ if (!simulator.status.apiUrl) {
204
+ throw new Error('Simulator instance not ready: apiUrl is not available');
205
+ }
206
+ simApiUrl = simulator.status.apiUrl;
207
+ simToken = simulator.status.token;
208
+ } else {
209
+ simApiUrl = simulator.apiUrl;
210
+ simToken = simulator.token;
211
+ }
212
+
213
+ const res = await nodeProxyTransport.fetch(`${apiUrl}/simulator`, {
214
+ method: 'POST',
215
+ headers: {
216
+ 'Content-Type': 'application/json',
217
+ Authorization: `Bearer ${token}`,
218
+ },
219
+ body: JSON.stringify({ apiUrl: simApiUrl, token: simToken }),
220
+ });
221
+ if (!res.ok) {
222
+ const text = await res.text();
223
+ throw new Error(`POST /simulator failed: ${res.status} ${text}`);
224
+ }
225
+ },
226
+ };
227
+ }
228
+ }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = '0.24.0'; // x-release-please-version
1
+ export const VERSION = '0.24.2'; // x-release-please-version
package/version.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.24.0";
1
+ export declare const VERSION = "0.24.2";
2
2
  //# sourceMappingURL=version.d.mts.map
package/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.24.0";
1
+ export declare const VERSION = "0.24.2";
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.24.0'; // x-release-please-version
4
+ exports.VERSION = '0.24.2'; // x-release-please-version
5
5
  //# sourceMappingURL=version.js.map
package/version.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '0.24.0'; // x-release-please-version
1
+ export const VERSION = '0.24.2'; // x-release-please-version
2
2
  //# sourceMappingURL=version.mjs.map
@@ -1,129 +0,0 @@
1
- import { ExecChildProcess } from "./exec-client.mjs";
2
- export type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'debug';
3
- /**
4
- * Build configuration for xcodebuild command.
5
- */
6
- export type XcodeBuildConfig = {
7
- workspace?: string;
8
- project?: string;
9
- scheme?: string;
10
- };
11
- /**
12
- * Simulator connection details for configuring the sandbox.
13
- */
14
- export type SimulatorConfig = {
15
- /** The API URL of the simulator (limulator) */
16
- apiUrl: string;
17
- /** Auth token for the simulator. If not provided, uses the sandbox token. */
18
- token?: string;
19
- };
20
- /**
21
- * Options for syncing source code to the sandbox.
22
- */
23
- export type SyncOptions = {
24
- /**
25
- * If true, watch the folder and re-sync on any changes. Defaults to true.
26
- */
27
- watch?: boolean;
28
- /**
29
- * Directory for the client-side folder-sync cache.
30
- * Used to store the last-synced “basis” copies of files (and related sync metadata) so we can compute xdelta patches
31
- * on subsequent syncs without re-downloading server state.
32
- *
33
- * Defaults to a temporary directory under the OS temp directory.
34
- */
35
- basisCacheDir?: string;
36
- /** Max patch size (bytes) to send as delta before falling back to full upload. */
37
- maxPatchBytes?: number;
38
- /** If true, install the app after syncing. Defaults to true. */
39
- install?: boolean;
40
- /**
41
- * Optional predicate for ignoring files and directories during sync.
42
- * Applied in addition to built-in sync and Xcode-specific ignore rules.
43
- * Called with the relative path from the sync root (using forward slashes).
44
- * For directories, the path ends with '/'.
45
- * Return true to ignore, false to keep.
46
- *
47
- * @example
48
- * // Ignore build folder
49
- * ignore: (path) => path.startsWith('build/')
50
- *
51
- * @example
52
- * // Ignore anything outside src/ and JSON files
53
- * ignore: (path) => !(path.startsWith('src/') || path.endsWith('.json'))
54
- */
55
- ignore?: (relativePath: string) => boolean;
56
- };
57
- /**
58
- * Result of a sync operation.
59
- */
60
- export type SyncResult = {
61
- /** Present only when watch=true; call to stop watching */
62
- stopWatching?: () => void;
63
- };
64
- /**
65
- * Client for interacting with a sandboxed Xcode build service.
66
- */
67
- export type XCodeSandboxClient = {
68
- /**
69
- * Sync source code to the sandbox. In watch mode, keeps syncing on changes.
70
- * Does NOT trigger builds - call xcodebuild() when ready.
71
- */
72
- sync: (localCodePath: string, opts?: SyncOptions) => Promise<SyncResult>;
73
- /**
74
- * Trigger xcodebuild on the synced source code.
75
- * Returns a ChildProcess-like object for streaming output.
76
- *
77
- * @example
78
- * // Stream build output
79
- * const build = client.xcodebuild();
80
- * build.stdout.on('data', (line) => console.log(line));
81
- * const { exitCode } = await build;
82
- */
83
- xcodebuild: (opts?: XcodeBuildConfig) => ExecChildProcess;
84
- };
85
- export type CreateXCodeSandboxClientOptions = {
86
- /** The API URL of the Xcode sandbox server */
87
- apiUrl: string;
88
- /** Auth token for the sandbox */
89
- token: string;
90
- /**
91
- * Simulator (limulator) connection details. Only needed if the sandbox is not
92
- * already configured (e.g., when created outside of an iOS instance).
93
- * When provided, the client will call POST /simulator to set up the connection.
94
- */
95
- simulator?: SimulatorConfig;
96
- /**
97
- * Controls logging verbosity
98
- * @default 'info'
99
- */
100
- logLevel?: LogLevel;
101
- };
102
- /**
103
- * Creates a client for interacting with a sandboxed Xcode build service.
104
- *
105
- * @example
106
- * // When using an iOS instance (simulator already configured):
107
- * const client = await createXCodeSandboxClient({
108
- * apiUrl: instance.status.sandbox.xcode.url,
109
- * token: apiKey,
110
- * });
111
- *
112
- * // When using a standalone sandbox (need to configure simulator):
113
- * const client = await createXCodeSandboxClient({
114
- * apiUrl: 'https://sandbox.example.com',
115
- * token: 'xxx',
116
- * simulator: {
117
- * apiUrl: 'https://limulator.example.com',
118
- * token: 'yyy', // optional, defaults to sandbox token
119
- * },
120
- * });
121
- *
122
- * // Sync code and build
123
- * await client.sync('./my-ios-app', { watch: true });
124
- * const build = client.xcodebuild();
125
- * build.stdout.on('data', (line) => console.log('[build]', line));
126
- * const { exitCode } = await build;
127
- */
128
- export declare function createXCodeSandboxClient(options: CreateXCodeSandboxClientOptions): Promise<XCodeSandboxClient>;
129
- //# sourceMappingURL=sandbox-client.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sandbox-client.d.mts","sourceRoot":"","sources":["src/sandbox-client.ts"],"names":[],"mappings":"OAGO,EAAQ,gBAAgB,EAAE;AAKjC,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;CAC5C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;OAGG;IACH,IAAI,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAEzE;;;;;;;;;OASG;IACH,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,gBAAgB,KAAK,gBAAgB,CAAC;CAC3D,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC5C,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,kBAAkB,CAAC,CAqI7B"}
@@ -1,129 +0,0 @@
1
- import { ExecChildProcess } from "./exec-client.js";
2
- export type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'debug';
3
- /**
4
- * Build configuration for xcodebuild command.
5
- */
6
- export type XcodeBuildConfig = {
7
- workspace?: string;
8
- project?: string;
9
- scheme?: string;
10
- };
11
- /**
12
- * Simulator connection details for configuring the sandbox.
13
- */
14
- export type SimulatorConfig = {
15
- /** The API URL of the simulator (limulator) */
16
- apiUrl: string;
17
- /** Auth token for the simulator. If not provided, uses the sandbox token. */
18
- token?: string;
19
- };
20
- /**
21
- * Options for syncing source code to the sandbox.
22
- */
23
- export type SyncOptions = {
24
- /**
25
- * If true, watch the folder and re-sync on any changes. Defaults to true.
26
- */
27
- watch?: boolean;
28
- /**
29
- * Directory for the client-side folder-sync cache.
30
- * Used to store the last-synced “basis” copies of files (and related sync metadata) so we can compute xdelta patches
31
- * on subsequent syncs without re-downloading server state.
32
- *
33
- * Defaults to a temporary directory under the OS temp directory.
34
- */
35
- basisCacheDir?: string;
36
- /** Max patch size (bytes) to send as delta before falling back to full upload. */
37
- maxPatchBytes?: number;
38
- /** If true, install the app after syncing. Defaults to true. */
39
- install?: boolean;
40
- /**
41
- * Optional predicate for ignoring files and directories during sync.
42
- * Applied in addition to built-in sync and Xcode-specific ignore rules.
43
- * Called with the relative path from the sync root (using forward slashes).
44
- * For directories, the path ends with '/'.
45
- * Return true to ignore, false to keep.
46
- *
47
- * @example
48
- * // Ignore build folder
49
- * ignore: (path) => path.startsWith('build/')
50
- *
51
- * @example
52
- * // Ignore anything outside src/ and JSON files
53
- * ignore: (path) => !(path.startsWith('src/') || path.endsWith('.json'))
54
- */
55
- ignore?: (relativePath: string) => boolean;
56
- };
57
- /**
58
- * Result of a sync operation.
59
- */
60
- export type SyncResult = {
61
- /** Present only when watch=true; call to stop watching */
62
- stopWatching?: () => void;
63
- };
64
- /**
65
- * Client for interacting with a sandboxed Xcode build service.
66
- */
67
- export type XCodeSandboxClient = {
68
- /**
69
- * Sync source code to the sandbox. In watch mode, keeps syncing on changes.
70
- * Does NOT trigger builds - call xcodebuild() when ready.
71
- */
72
- sync: (localCodePath: string, opts?: SyncOptions) => Promise<SyncResult>;
73
- /**
74
- * Trigger xcodebuild on the synced source code.
75
- * Returns a ChildProcess-like object for streaming output.
76
- *
77
- * @example
78
- * // Stream build output
79
- * const build = client.xcodebuild();
80
- * build.stdout.on('data', (line) => console.log(line));
81
- * const { exitCode } = await build;
82
- */
83
- xcodebuild: (opts?: XcodeBuildConfig) => ExecChildProcess;
84
- };
85
- export type CreateXCodeSandboxClientOptions = {
86
- /** The API URL of the Xcode sandbox server */
87
- apiUrl: string;
88
- /** Auth token for the sandbox */
89
- token: string;
90
- /**
91
- * Simulator (limulator) connection details. Only needed if the sandbox is not
92
- * already configured (e.g., when created outside of an iOS instance).
93
- * When provided, the client will call POST /simulator to set up the connection.
94
- */
95
- simulator?: SimulatorConfig;
96
- /**
97
- * Controls logging verbosity
98
- * @default 'info'
99
- */
100
- logLevel?: LogLevel;
101
- };
102
- /**
103
- * Creates a client for interacting with a sandboxed Xcode build service.
104
- *
105
- * @example
106
- * // When using an iOS instance (simulator already configured):
107
- * const client = await createXCodeSandboxClient({
108
- * apiUrl: instance.status.sandbox.xcode.url,
109
- * token: apiKey,
110
- * });
111
- *
112
- * // When using a standalone sandbox (need to configure simulator):
113
- * const client = await createXCodeSandboxClient({
114
- * apiUrl: 'https://sandbox.example.com',
115
- * token: 'xxx',
116
- * simulator: {
117
- * apiUrl: 'https://limulator.example.com',
118
- * token: 'yyy', // optional, defaults to sandbox token
119
- * },
120
- * });
121
- *
122
- * // Sync code and build
123
- * await client.sync('./my-ios-app', { watch: true });
124
- * const build = client.xcodebuild();
125
- * build.stdout.on('data', (line) => console.log('[build]', line));
126
- * const { exitCode } = await build;
127
- */
128
- export declare function createXCodeSandboxClient(options: CreateXCodeSandboxClientOptions): Promise<XCodeSandboxClient>;
129
- //# sourceMappingURL=sandbox-client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sandbox-client.d.ts","sourceRoot":"","sources":["src/sandbox-client.ts"],"names":[],"mappings":"OAGO,EAAQ,gBAAgB,EAAE;AAKjC,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kFAAkF;IAClF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;CAC5C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;OAGG;IACH,IAAI,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAEzE;;;;;;;;;OASG;IACH,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,gBAAgB,KAAK,gBAAgB,CAAC;CAC3D,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC5C,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,kBAAkB,CAAC,CAqI7B"}