@limrun/api 0.19.3 → 0.20.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 (68) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/client.d.mts +1 -0
  3. package/client.d.mts.map +1 -1
  4. package/client.d.ts +1 -0
  5. package/client.d.ts.map +1 -1
  6. package/client.js +10 -2
  7. package/client.js.map +1 -1
  8. package/client.mjs +10 -2
  9. package/client.mjs.map +1 -1
  10. package/exec-client.d.mts +101 -0
  11. package/exec-client.d.mts.map +1 -0
  12. package/exec-client.d.ts +101 -0
  13. package/exec-client.d.ts.map +1 -0
  14. package/exec-client.js +265 -0
  15. package/exec-client.js.map +1 -0
  16. package/exec-client.mjs +259 -0
  17. package/exec-client.mjs.map +1 -0
  18. package/folder-sync.d.mts +16 -2
  19. package/folder-sync.d.mts.map +1 -1
  20. package/folder-sync.d.ts +16 -2
  21. package/folder-sync.d.ts.map +1 -1
  22. package/folder-sync.js +43 -14
  23. package/folder-sync.js.map +1 -1
  24. package/folder-sync.mjs +43 -13
  25. package/folder-sync.mjs.map +1 -1
  26. package/index.d.mts +2 -0
  27. package/index.d.mts.map +1 -1
  28. package/index.d.ts +2 -0
  29. package/index.d.ts.map +1 -1
  30. package/index.js +5 -1
  31. package/index.js.map +1 -1
  32. package/index.mjs +2 -0
  33. package/index.mjs.map +1 -1
  34. package/internal/parse.d.mts.map +1 -1
  35. package/internal/parse.d.ts.map +1 -1
  36. package/internal/parse.js +5 -0
  37. package/internal/parse.js.map +1 -1
  38. package/internal/parse.mjs +5 -0
  39. package/internal/parse.mjs.map +1 -1
  40. package/ios-client.d.mts +10 -3
  41. package/ios-client.d.mts.map +1 -1
  42. package/ios-client.d.ts +10 -3
  43. package/ios-client.d.ts.map +1 -1
  44. package/ios-client.js +19 -4
  45. package/ios-client.js.map +1 -1
  46. package/ios-client.mjs +18 -3
  47. package/ios-client.mjs.map +1 -1
  48. package/package.json +23 -1
  49. package/sandbox-client.d.mts +124 -0
  50. package/sandbox-client.d.mts.map +1 -0
  51. package/sandbox-client.d.ts +124 -0
  52. package/sandbox-client.d.ts.map +1 -0
  53. package/sandbox-client.js +149 -0
  54. package/sandbox-client.js.map +1 -0
  55. package/sandbox-client.mjs +146 -0
  56. package/sandbox-client.mjs.map +1 -0
  57. package/src/client.ts +10 -2
  58. package/src/exec-client.ts +333 -0
  59. package/src/folder-sync.ts +66 -18
  60. package/src/index.ts +16 -0
  61. package/src/internal/parse.ts +6 -0
  62. package/src/ios-client.ts +35 -5
  63. package/src/sandbox-client.ts +267 -0
  64. package/src/version.ts +1 -1
  65. package/version.d.mts +1 -1
  66. package/version.d.ts +1 -1
  67. package/version.js +1 -1
  68. package/version.mjs +1 -1
@@ -0,0 +1,267 @@
1
+ import { syncApp as syncFolderImpl, type FolderSyncOptions } from './folder-sync';
2
+ import { exec, ExecChildProcess } from './exec-client';
3
+
4
+ export type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'debug';
5
+
6
+ /**
7
+ * Build configuration for xcodebuild command.
8
+ */
9
+ export type XcodeBuildConfig = {
10
+ workspace?: string;
11
+ project?: string;
12
+ scheme?: string;
13
+ };
14
+
15
+ /**
16
+ * Simulator connection details for configuring the sandbox.
17
+ */
18
+ export type SimulatorConfig = {
19
+ /** The API URL of the simulator (limulator) */
20
+ apiUrl: string;
21
+ /** Auth token for the simulator. If not provided, uses the sandbox token. */
22
+ token?: string;
23
+ };
24
+
25
+ /**
26
+ * Options for syncing source code to the sandbox.
27
+ */
28
+ export type SyncOptions = {
29
+ /**
30
+ * Cache scoping key for delta basis caching. Defaults to 'xcode-sandbox'.
31
+ * This is not sent to the server.
32
+ */
33
+ cacheKey?: string;
34
+ basisCacheDir?: string;
35
+ maxPatchBytes?: number;
36
+ /**
37
+ * If true, watch the folder and re-sync on any changes.
38
+ */
39
+ watch?: boolean;
40
+ log?: (level: 'debug' | 'info' | 'warn' | 'error', msg: string) => void;
41
+ /**
42
+ * Optional filter function to include/exclude files and directories.
43
+ * Called with the relative path from the sync root (using forward slashes).
44
+ * For directories, the path ends with '/'.
45
+ * Return true to include, false to exclude.
46
+ *
47
+ * @example
48
+ * // Exclude build folder
49
+ * filter: (path) => !path.startsWith('build/')
50
+ *
51
+ * @example
52
+ * // Only include source files
53
+ * filter: (path) => path.startsWith('src/') || path.endsWith('.json')
54
+ */
55
+ filter?: (relativePath: string) => boolean;
56
+ };
57
+
58
+ /**
59
+ * Result of a sync operation.
60
+ */
61
+ export type SyncResult = {
62
+ /** Present only when watch=true; call to stop watching */
63
+ stopWatching?: () => void;
64
+ };
65
+
66
+ /**
67
+ * Client for interacting with a sandboxed Xcode build service.
68
+ */
69
+ export type XCodeSandboxClient = {
70
+ /**
71
+ * Sync source code to the sandbox. In watch mode, keeps syncing on changes.
72
+ * Does NOT trigger builds - call xcodebuild() when ready.
73
+ */
74
+ sync: (localCodePath: string, opts?: SyncOptions) => Promise<SyncResult>;
75
+
76
+ /**
77
+ * Trigger xcodebuild on the synced source code.
78
+ * Returns a ChildProcess-like object for streaming output.
79
+ *
80
+ * @example
81
+ * // Stream build output
82
+ * const build = client.xcodebuild();
83
+ * build.stdout.on('data', (line) => console.log(line));
84
+ * const { exitCode } = await build;
85
+ */
86
+ xcodebuild: (opts?: XcodeBuildConfig) => ExecChildProcess;
87
+ };
88
+
89
+ export type CreateXCodeSandboxClientOptions = {
90
+ /** The API URL of the Xcode sandbox server */
91
+ apiUrl: string;
92
+ /** Auth token for the sandbox */
93
+ token: string;
94
+ /**
95
+ * Simulator (limulator) connection details. Only needed if the sandbox is not
96
+ * already configured (e.g., when created outside of an iOS instance).
97
+ * When provided, the client will call POST /simulator to set up the connection.
98
+ */
99
+ simulator?: SimulatorConfig;
100
+ /**
101
+ * Controls logging verbosity
102
+ * @default 'info'
103
+ */
104
+ logLevel?: LogLevel;
105
+ };
106
+
107
+ /**
108
+ * Creates a client for interacting with a sandboxed Xcode build service.
109
+ *
110
+ * @example
111
+ * // When using an iOS instance (simulator already configured):
112
+ * const client = await createXCodeSandboxClient({
113
+ * apiUrl: instance.status.sandbox.xcode.url,
114
+ * token: apiKey,
115
+ * });
116
+ *
117
+ * // When using a standalone sandbox (need to configure simulator):
118
+ * const client = await createXCodeSandboxClient({
119
+ * apiUrl: 'https://sandbox.example.com',
120
+ * token: 'xxx',
121
+ * simulator: {
122
+ * apiUrl: 'https://limulator.example.com',
123
+ * token: 'yyy', // optional, defaults to sandbox token
124
+ * },
125
+ * });
126
+ *
127
+ * // Sync code and build
128
+ * await client.sync('./my-ios-app', { watch: true });
129
+ * const build = client.xcodebuild();
130
+ * build.stdout.on('data', (line) => console.log('[build]', line));
131
+ * const { exitCode } = await build;
132
+ */
133
+ export async function createXCodeSandboxClient(
134
+ options: CreateXCodeSandboxClientOptions,
135
+ ): Promise<XCodeSandboxClient> {
136
+ const logLevel = options.logLevel ?? 'info';
137
+ const logger = {
138
+ debug: (...args: unknown[]) => {
139
+ if (logLevel === 'debug') console.log('[XCodeSandbox]', ...args);
140
+ },
141
+ info: (...args: unknown[]) => {
142
+ if (logLevel === 'info' || logLevel === 'debug') console.log('[XCodeSandbox]', ...args);
143
+ },
144
+ warn: (...args: unknown[]) => {
145
+ if (logLevel === 'warn' || logLevel === 'info' || logLevel === 'debug')
146
+ console.warn('[XCodeSandbox]', ...args);
147
+ },
148
+ error: (...args: unknown[]) => {
149
+ if (logLevel !== 'none') console.error('[XCodeSandbox]', ...args);
150
+ },
151
+ };
152
+
153
+ const logFn = (level: 'debug' | 'info' | 'warn' | 'error', msg: string) => {
154
+ switch (level) {
155
+ case 'debug':
156
+ logger.debug(msg);
157
+ break;
158
+ case 'info':
159
+ logger.info(msg);
160
+ break;
161
+ case 'warn':
162
+ logger.warn(msg);
163
+ break;
164
+ case 'error':
165
+ logger.error(msg);
166
+ break;
167
+ default:
168
+ logger.info(msg);
169
+ break;
170
+ }
171
+ };
172
+
173
+ // Configure the simulator connection if provided
174
+ if (options.simulator) {
175
+ const cfg: {
176
+ simulatorApiUrl?: string;
177
+ simulatorToken?: string;
178
+ } = {
179
+ simulatorApiUrl: options.simulator.apiUrl,
180
+ simulatorToken: options.simulator.token ?? options.token,
181
+ };
182
+
183
+ const res = await fetch(`${options.apiUrl}/simulator`, {
184
+ method: 'POST',
185
+ headers: {
186
+ 'Content-Type': 'application/json',
187
+ Authorization: `Bearer ${options.token}`,
188
+ },
189
+ body: JSON.stringify(cfg),
190
+ });
191
+ const text = await res.text();
192
+ if (!res.ok) {
193
+ throw new Error(`POST /simulator failed: ${res.status} ${text}`);
194
+ }
195
+ }
196
+
197
+ return {
198
+ async sync(localCodePath: string, opts?: SyncOptions): Promise<SyncResult> {
199
+ const codeSyncOpts: FolderSyncOptions = {
200
+ apiUrl: options.apiUrl,
201
+ token: options.token,
202
+ udid: opts?.cacheKey ?? 'xcode-sandbox',
203
+ install: false,
204
+ filter: (relativePath: string) => {
205
+ if (
206
+ relativePath.startsWith('build/') ||
207
+ relativePath.startsWith('.build/') ||
208
+ relativePath.startsWith('DerivedData/') ||
209
+ relativePath.startsWith('Index.noindex/') ||
210
+ relativePath.startsWith('ModuleCache.noindex/') ||
211
+ relativePath.startsWith('.index-build/')
212
+ ) {
213
+ return false;
214
+ }
215
+ if (
216
+ relativePath.startsWith('.swiftpm/') ||
217
+ relativePath.startsWith('Pods/') ||
218
+ relativePath.startsWith('Carthage/Build/')
219
+ ) {
220
+ return false;
221
+ }
222
+ if (
223
+ relativePath.startsWith('.git/') ||
224
+ relativePath.startsWith('.limsync-cache/') ||
225
+ relativePath === '.DS_Store' ||
226
+ relativePath.endsWith('/.DS_Store')
227
+ ) {
228
+ return false;
229
+ }
230
+ if (relativePath.includes('/xcuserdata/')) {
231
+ return false;
232
+ }
233
+ if (relativePath.includes('.dSYM/')) {
234
+ return false;
235
+ }
236
+
237
+ // User-provided filter
238
+ if (opts?.filter && !opts.filter(relativePath)) {
239
+ return false;
240
+ }
241
+ return true;
242
+ },
243
+ ...(opts?.basisCacheDir ? { basisCacheDir: opts.basisCacheDir } : {}),
244
+ ...(opts?.maxPatchBytes !== undefined ? { maxPatchBytes: opts.maxPatchBytes } : {}),
245
+ ...(opts?.watch !== undefined ? { watch: opts.watch } : {}),
246
+ log: opts?.log ?? logFn,
247
+ };
248
+
249
+ const result = await syncFolderImpl(localCodePath, codeSyncOpts);
250
+ if (result.stopWatching) {
251
+ return { stopWatching: result.stopWatching };
252
+ }
253
+ return {};
254
+ },
255
+
256
+ xcodebuild(opts?: XcodeBuildConfig): ExecChildProcess {
257
+ return exec(
258
+ { command: 'xcodebuild', ...(opts && { xcodebuild: opts }) },
259
+ {
260
+ apiUrl: options.apiUrl,
261
+ token: options.token,
262
+ log: logFn,
263
+ },
264
+ );
265
+ },
266
+ };
267
+ }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = '0.19.3'; // x-release-please-version
1
+ export const VERSION = '0.20.0'; // x-release-please-version
package/version.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.19.3";
1
+ export declare const VERSION = "0.20.0";
2
2
  //# sourceMappingURL=version.d.mts.map
package/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.19.3";
1
+ export declare const VERSION = "0.20.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.19.3'; // x-release-please-version
4
+ exports.VERSION = '0.20.0'; // x-release-please-version
5
5
  //# sourceMappingURL=version.js.map
package/version.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '0.19.3'; // x-release-please-version
1
+ export const VERSION = '0.20.0'; // x-release-please-version
2
2
  //# sourceMappingURL=version.mjs.map