@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.
- package/CHANGELOG.md +15 -0
- package/client.d.mts +1 -0
- package/client.d.mts.map +1 -1
- package/client.d.ts +1 -0
- package/client.d.ts.map +1 -1
- package/client.js +10 -2
- package/client.js.map +1 -1
- package/client.mjs +10 -2
- package/client.mjs.map +1 -1
- package/exec-client.d.mts +101 -0
- package/exec-client.d.mts.map +1 -0
- package/exec-client.d.ts +101 -0
- package/exec-client.d.ts.map +1 -0
- package/exec-client.js +265 -0
- package/exec-client.js.map +1 -0
- package/exec-client.mjs +259 -0
- package/exec-client.mjs.map +1 -0
- package/folder-sync.d.mts +16 -2
- package/folder-sync.d.mts.map +1 -1
- package/folder-sync.d.ts +16 -2
- package/folder-sync.d.ts.map +1 -1
- package/folder-sync.js +43 -14
- package/folder-sync.js.map +1 -1
- package/folder-sync.mjs +43 -13
- package/folder-sync.mjs.map +1 -1
- package/index.d.mts +2 -0
- package/index.d.mts.map +1 -1
- package/index.d.ts +2 -0
- package/index.d.ts.map +1 -1
- package/index.js +5 -1
- package/index.js.map +1 -1
- package/index.mjs +2 -0
- package/index.mjs.map +1 -1
- package/internal/parse.d.mts.map +1 -1
- package/internal/parse.d.ts.map +1 -1
- package/internal/parse.js +5 -0
- package/internal/parse.js.map +1 -1
- package/internal/parse.mjs +5 -0
- package/internal/parse.mjs.map +1 -1
- package/ios-client.d.mts +10 -3
- package/ios-client.d.mts.map +1 -1
- package/ios-client.d.ts +10 -3
- package/ios-client.d.ts.map +1 -1
- package/ios-client.js +19 -4
- package/ios-client.js.map +1 -1
- package/ios-client.mjs +18 -3
- package/ios-client.mjs.map +1 -1
- package/package.json +23 -1
- package/sandbox-client.d.mts +124 -0
- package/sandbox-client.d.mts.map +1 -0
- package/sandbox-client.d.ts +124 -0
- package/sandbox-client.d.ts.map +1 -0
- package/sandbox-client.js +149 -0
- package/sandbox-client.js.map +1 -0
- package/sandbox-client.mjs +146 -0
- package/sandbox-client.mjs.map +1 -0
- package/src/client.ts +10 -2
- package/src/exec-client.ts +333 -0
- package/src/folder-sync.ts +66 -18
- package/src/index.ts +16 -0
- package/src/internal/parse.ts +6 -0
- package/src/ios-client.ts +35 -5
- package/src/sandbox-client.ts +267 -0
- package/src/version.ts +1 -1
- package/version.d.mts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
|
@@ -0,0 +1,124 @@
|
|
|
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
|
+
* Cache scoping key for delta basis caching. Defaults to 'xcode-sandbox'.
|
|
26
|
+
* This is not sent to the server.
|
|
27
|
+
*/
|
|
28
|
+
cacheKey?: string;
|
|
29
|
+
basisCacheDir?: string;
|
|
30
|
+
maxPatchBytes?: number;
|
|
31
|
+
/**
|
|
32
|
+
* If true, watch the folder and re-sync on any changes.
|
|
33
|
+
*/
|
|
34
|
+
watch?: boolean;
|
|
35
|
+
log?: (level: 'debug' | 'info' | 'warn' | 'error', msg: string) => void;
|
|
36
|
+
/**
|
|
37
|
+
* Optional filter function to include/exclude files and directories.
|
|
38
|
+
* Called with the relative path from the sync root (using forward slashes).
|
|
39
|
+
* For directories, the path ends with '/'.
|
|
40
|
+
* Return true to include, false to exclude.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* // Exclude build folder
|
|
44
|
+
* filter: (path) => !path.startsWith('build/')
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // Only include source files
|
|
48
|
+
* filter: (path) => path.startsWith('src/') || path.endsWith('.json')
|
|
49
|
+
*/
|
|
50
|
+
filter?: (relativePath: string) => boolean;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Result of a sync operation.
|
|
54
|
+
*/
|
|
55
|
+
export type SyncResult = {
|
|
56
|
+
/** Present only when watch=true; call to stop watching */
|
|
57
|
+
stopWatching?: () => void;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Client for interacting with a sandboxed Xcode build service.
|
|
61
|
+
*/
|
|
62
|
+
export type XCodeSandboxClient = {
|
|
63
|
+
/**
|
|
64
|
+
* Sync source code to the sandbox. In watch mode, keeps syncing on changes.
|
|
65
|
+
* Does NOT trigger builds - call xcodebuild() when ready.
|
|
66
|
+
*/
|
|
67
|
+
sync: (localCodePath: string, opts?: SyncOptions) => Promise<SyncResult>;
|
|
68
|
+
/**
|
|
69
|
+
* Trigger xcodebuild on the synced source code.
|
|
70
|
+
* Returns a ChildProcess-like object for streaming output.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* // Stream build output
|
|
74
|
+
* const build = client.xcodebuild();
|
|
75
|
+
* build.stdout.on('data', (line) => console.log(line));
|
|
76
|
+
* const { exitCode } = await build;
|
|
77
|
+
*/
|
|
78
|
+
xcodebuild: (opts?: XcodeBuildConfig) => ExecChildProcess;
|
|
79
|
+
};
|
|
80
|
+
export type CreateXCodeSandboxClientOptions = {
|
|
81
|
+
/** The API URL of the Xcode sandbox server */
|
|
82
|
+
apiUrl: string;
|
|
83
|
+
/** Auth token for the sandbox */
|
|
84
|
+
token: string;
|
|
85
|
+
/**
|
|
86
|
+
* Simulator (limulator) connection details. Only needed if the sandbox is not
|
|
87
|
+
* already configured (e.g., when created outside of an iOS instance).
|
|
88
|
+
* When provided, the client will call POST /simulator to set up the connection.
|
|
89
|
+
*/
|
|
90
|
+
simulator?: SimulatorConfig;
|
|
91
|
+
/**
|
|
92
|
+
* Controls logging verbosity
|
|
93
|
+
* @default 'info'
|
|
94
|
+
*/
|
|
95
|
+
logLevel?: LogLevel;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Creates a client for interacting with a sandboxed Xcode build service.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* // When using an iOS instance (simulator already configured):
|
|
102
|
+
* const client = await createXCodeSandboxClient({
|
|
103
|
+
* apiUrl: instance.status.sandbox.xcode.url,
|
|
104
|
+
* token: apiKey,
|
|
105
|
+
* });
|
|
106
|
+
*
|
|
107
|
+
* // When using a standalone sandbox (need to configure simulator):
|
|
108
|
+
* const client = await createXCodeSandboxClient({
|
|
109
|
+
* apiUrl: 'https://sandbox.example.com',
|
|
110
|
+
* token: 'xxx',
|
|
111
|
+
* simulator: {
|
|
112
|
+
* apiUrl: 'https://limulator.example.com',
|
|
113
|
+
* token: 'yyy', // optional, defaults to sandbox token
|
|
114
|
+
* },
|
|
115
|
+
* });
|
|
116
|
+
*
|
|
117
|
+
* // Sync code and build
|
|
118
|
+
* await client.sync('./my-ios-app', { watch: true });
|
|
119
|
+
* const build = client.xcodebuild();
|
|
120
|
+
* build.stdout.on('data', (line) => console.log('[build]', line));
|
|
121
|
+
* const { exitCode } = await build;
|
|
122
|
+
*/
|
|
123
|
+
export declare function createXCodeSandboxClient(options: CreateXCodeSandboxClientOptions): Promise<XCodeSandboxClient>;
|
|
124
|
+
//# sourceMappingURL=sandbox-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-client.d.ts","sourceRoot":"","sources":["src/sandbox-client.ts"],"names":[],"mappings":"OACO,EAAQ,gBAAgB,EAAE;AAEjC,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;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE;;;;;;;;;;;;;OAaG;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,CAoI7B"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createXCodeSandboxClient = createXCodeSandboxClient;
|
|
4
|
+
const folder_sync_1 = require("./folder-sync.js");
|
|
5
|
+
const exec_client_1 = require("./exec-client.js");
|
|
6
|
+
/**
|
|
7
|
+
* Creates a client for interacting with a sandboxed Xcode build service.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // When using an iOS instance (simulator already configured):
|
|
11
|
+
* const client = await createXCodeSandboxClient({
|
|
12
|
+
* apiUrl: instance.status.sandbox.xcode.url,
|
|
13
|
+
* token: apiKey,
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* // When using a standalone sandbox (need to configure simulator):
|
|
17
|
+
* const client = await createXCodeSandboxClient({
|
|
18
|
+
* apiUrl: 'https://sandbox.example.com',
|
|
19
|
+
* token: 'xxx',
|
|
20
|
+
* simulator: {
|
|
21
|
+
* apiUrl: 'https://limulator.example.com',
|
|
22
|
+
* token: 'yyy', // optional, defaults to sandbox token
|
|
23
|
+
* },
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Sync code and build
|
|
27
|
+
* await client.sync('./my-ios-app', { watch: true });
|
|
28
|
+
* const build = client.xcodebuild();
|
|
29
|
+
* build.stdout.on('data', (line) => console.log('[build]', line));
|
|
30
|
+
* const { exitCode } = await build;
|
|
31
|
+
*/
|
|
32
|
+
async function createXCodeSandboxClient(options) {
|
|
33
|
+
const logLevel = options.logLevel ?? 'info';
|
|
34
|
+
const logger = {
|
|
35
|
+
debug: (...args) => {
|
|
36
|
+
if (logLevel === 'debug')
|
|
37
|
+
console.log('[XCodeSandbox]', ...args);
|
|
38
|
+
},
|
|
39
|
+
info: (...args) => {
|
|
40
|
+
if (logLevel === 'info' || logLevel === 'debug')
|
|
41
|
+
console.log('[XCodeSandbox]', ...args);
|
|
42
|
+
},
|
|
43
|
+
warn: (...args) => {
|
|
44
|
+
if (logLevel === 'warn' || logLevel === 'info' || logLevel === 'debug')
|
|
45
|
+
console.warn('[XCodeSandbox]', ...args);
|
|
46
|
+
},
|
|
47
|
+
error: (...args) => {
|
|
48
|
+
if (logLevel !== 'none')
|
|
49
|
+
console.error('[XCodeSandbox]', ...args);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
const logFn = (level, msg) => {
|
|
53
|
+
switch (level) {
|
|
54
|
+
case 'debug':
|
|
55
|
+
logger.debug(msg);
|
|
56
|
+
break;
|
|
57
|
+
case 'info':
|
|
58
|
+
logger.info(msg);
|
|
59
|
+
break;
|
|
60
|
+
case 'warn':
|
|
61
|
+
logger.warn(msg);
|
|
62
|
+
break;
|
|
63
|
+
case 'error':
|
|
64
|
+
logger.error(msg);
|
|
65
|
+
break;
|
|
66
|
+
default:
|
|
67
|
+
logger.info(msg);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
// Configure the simulator connection if provided
|
|
72
|
+
if (options.simulator) {
|
|
73
|
+
const cfg = {
|
|
74
|
+
simulatorApiUrl: options.simulator.apiUrl,
|
|
75
|
+
simulatorToken: options.simulator.token ?? options.token,
|
|
76
|
+
};
|
|
77
|
+
const res = await fetch(`${options.apiUrl}/simulator`, {
|
|
78
|
+
method: 'POST',
|
|
79
|
+
headers: {
|
|
80
|
+
'Content-Type': 'application/json',
|
|
81
|
+
Authorization: `Bearer ${options.token}`,
|
|
82
|
+
},
|
|
83
|
+
body: JSON.stringify(cfg),
|
|
84
|
+
});
|
|
85
|
+
const text = await res.text();
|
|
86
|
+
if (!res.ok) {
|
|
87
|
+
throw new Error(`POST /simulator failed: ${res.status} ${text}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
async sync(localCodePath, opts) {
|
|
92
|
+
const codeSyncOpts = {
|
|
93
|
+
apiUrl: options.apiUrl,
|
|
94
|
+
token: options.token,
|
|
95
|
+
udid: opts?.cacheKey ?? 'xcode-sandbox',
|
|
96
|
+
install: false,
|
|
97
|
+
filter: (relativePath) => {
|
|
98
|
+
if (relativePath.startsWith('build/') ||
|
|
99
|
+
relativePath.startsWith('.build/') ||
|
|
100
|
+
relativePath.startsWith('DerivedData/') ||
|
|
101
|
+
relativePath.startsWith('Index.noindex/') ||
|
|
102
|
+
relativePath.startsWith('ModuleCache.noindex/') ||
|
|
103
|
+
relativePath.startsWith('.index-build/')) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
if (relativePath.startsWith('.swiftpm/') ||
|
|
107
|
+
relativePath.startsWith('Pods/') ||
|
|
108
|
+
relativePath.startsWith('Carthage/Build/')) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
if (relativePath.startsWith('.git/') ||
|
|
112
|
+
relativePath.startsWith('.limsync-cache/') ||
|
|
113
|
+
relativePath === '.DS_Store' ||
|
|
114
|
+
relativePath.endsWith('/.DS_Store')) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
if (relativePath.includes('/xcuserdata/')) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if (relativePath.includes('.dSYM/')) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
// User-provided filter
|
|
124
|
+
if (opts?.filter && !opts.filter(relativePath)) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
return true;
|
|
128
|
+
},
|
|
129
|
+
...(opts?.basisCacheDir ? { basisCacheDir: opts.basisCacheDir } : {}),
|
|
130
|
+
...(opts?.maxPatchBytes !== undefined ? { maxPatchBytes: opts.maxPatchBytes } : {}),
|
|
131
|
+
...(opts?.watch !== undefined ? { watch: opts.watch } : {}),
|
|
132
|
+
log: opts?.log ?? logFn,
|
|
133
|
+
};
|
|
134
|
+
const result = await (0, folder_sync_1.syncApp)(localCodePath, codeSyncOpts);
|
|
135
|
+
if (result.stopWatching) {
|
|
136
|
+
return { stopWatching: result.stopWatching };
|
|
137
|
+
}
|
|
138
|
+
return {};
|
|
139
|
+
},
|
|
140
|
+
xcodebuild(opts) {
|
|
141
|
+
return (0, exec_client_1.exec)({ command: 'xcodebuild', ...(opts && { xcodebuild: opts }) }, {
|
|
142
|
+
apiUrl: options.apiUrl,
|
|
143
|
+
token: options.token,
|
|
144
|
+
log: logFn,
|
|
145
|
+
});
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=sandbox-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-client.js","sourceRoot":"","sources":["src/sandbox-client.ts"],"names":[],"mappings":";;AAoIA,4DAsIC;AA1QD,kDAAkF;AAClF,kDAAuD;AAyGvD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACI,KAAK,UAAU,wBAAwB,CAC5C,OAAwC;IAExC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC;IAC5C,MAAM,MAAM,GAAG;QACb,KAAK,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE;YAC5B,IAAI,QAAQ,KAAK,OAAO;gBAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE;YAC3B,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,OAAO;gBAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1F,CAAC;QACD,IAAI,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE;YAC3B,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,OAAO;gBACpE,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,CAAC;QAC5C,CAAC;QACD,KAAK,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE;YAC5B,IAAI,QAAQ,KAAK,MAAM;gBAAE,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,CAAC;QACpE,CAAC;KACF,CAAC;IAEF,MAAM,KAAK,GAAG,CAAC,KAA0C,EAAE,GAAW,EAAE,EAAE;QACxE,QAAQ,KAAK,EAAE,CAAC;YACd,KAAK,OAAO;gBACV,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAClB,MAAM;YACR,KAAK,MAAM;gBACT,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACjB,MAAM;YACR,KAAK,MAAM;gBACT,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACjB,MAAM;YACR,KAAK,OAAO;gBACV,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAClB,MAAM;YACR;gBACE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACjB,MAAM;QACV,CAAC;IACH,CAAC,CAAC;IAEF,iDAAiD;IACjD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,GAAG,GAGL;YACF,eAAe,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM;YACzC,cAAc,EAAE,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK;SACzD,CAAC;QAEF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,YAAY,EAAE;YACrD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,OAAO,CAAC,KAAK,EAAE;aACzC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;SAC1B,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,aAAqB,EAAE,IAAkB;YAClD,MAAM,YAAY,GAAsB;gBACtC,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,IAAI,EAAE,IAAI,EAAE,QAAQ,IAAI,eAAe;gBACvC,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,CAAC,YAAoB,EAAE,EAAE;oBAC/B,IACE,YAAY,CAAC,UAAU,CAAC,QAAQ,CAAC;wBACjC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC;wBAClC,YAAY,CAAC,UAAU,CAAC,cAAc,CAAC;wBACvC,YAAY,CAAC,UAAU,CAAC,gBAAgB,CAAC;wBACzC,YAAY,CAAC,UAAU,CAAC,sBAAsB,CAAC;wBAC/C,YAAY,CAAC,UAAU,CAAC,eAAe,CAAC,EACxC,CAAC;wBACD,OAAO,KAAK,CAAC;oBACf,CAAC;oBACD,IACE,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC;wBACpC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC;wBAChC,YAAY,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAC1C,CAAC;wBACD,OAAO,KAAK,CAAC;oBACf,CAAC;oBACD,IACE,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC;wBAChC,YAAY,CAAC,UAAU,CAAC,iBAAiB,CAAC;wBAC1C,YAAY,KAAK,WAAW;wBAC5B,YAAY,CAAC,QAAQ,CAAC,YAAY,CAAC,EACnC,CAAC;wBACD,OAAO,KAAK,CAAC;oBACf,CAAC;oBACD,IAAI,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;wBAC1C,OAAO,KAAK,CAAC;oBACf,CAAC;oBACD,IAAI,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;wBACpC,OAAO,KAAK,CAAC;oBACf,CAAC;oBAED,uBAAuB;oBACvB,IAAI,IAAI,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;wBAC/C,OAAO,KAAK,CAAC;oBACf,CAAC;oBACD,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,GAAG,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrE,GAAG,CAAC,IAAI,EAAE,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnF,GAAG,CAAC,IAAI,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3D,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,KAAK;aACxB,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAc,EAAC,aAAa,EAAE,YAAY,CAAC,CAAC;YACjE,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;gBACxB,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;YAC/C,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,UAAU,CAAC,IAAuB;YAChC,OAAO,IAAA,kBAAI,EACT,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,EAC5D;gBACE,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,GAAG,EAAE,KAAK;aACX,CACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { syncApp as syncFolderImpl } from "./folder-sync.mjs";
|
|
2
|
+
import { exec } from "./exec-client.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a client for interacting with a sandboxed Xcode build service.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* // When using an iOS instance (simulator already configured):
|
|
8
|
+
* const client = await createXCodeSandboxClient({
|
|
9
|
+
* apiUrl: instance.status.sandbox.xcode.url,
|
|
10
|
+
* token: apiKey,
|
|
11
|
+
* });
|
|
12
|
+
*
|
|
13
|
+
* // When using a standalone sandbox (need to configure simulator):
|
|
14
|
+
* const client = await createXCodeSandboxClient({
|
|
15
|
+
* apiUrl: 'https://sandbox.example.com',
|
|
16
|
+
* token: 'xxx',
|
|
17
|
+
* simulator: {
|
|
18
|
+
* apiUrl: 'https://limulator.example.com',
|
|
19
|
+
* token: 'yyy', // optional, defaults to sandbox token
|
|
20
|
+
* },
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* // Sync code and build
|
|
24
|
+
* await client.sync('./my-ios-app', { watch: true });
|
|
25
|
+
* const build = client.xcodebuild();
|
|
26
|
+
* build.stdout.on('data', (line) => console.log('[build]', line));
|
|
27
|
+
* const { exitCode } = await build;
|
|
28
|
+
*/
|
|
29
|
+
export async function createXCodeSandboxClient(options) {
|
|
30
|
+
const logLevel = options.logLevel ?? 'info';
|
|
31
|
+
const logger = {
|
|
32
|
+
debug: (...args) => {
|
|
33
|
+
if (logLevel === 'debug')
|
|
34
|
+
console.log('[XCodeSandbox]', ...args);
|
|
35
|
+
},
|
|
36
|
+
info: (...args) => {
|
|
37
|
+
if (logLevel === 'info' || logLevel === 'debug')
|
|
38
|
+
console.log('[XCodeSandbox]', ...args);
|
|
39
|
+
},
|
|
40
|
+
warn: (...args) => {
|
|
41
|
+
if (logLevel === 'warn' || logLevel === 'info' || logLevel === 'debug')
|
|
42
|
+
console.warn('[XCodeSandbox]', ...args);
|
|
43
|
+
},
|
|
44
|
+
error: (...args) => {
|
|
45
|
+
if (logLevel !== 'none')
|
|
46
|
+
console.error('[XCodeSandbox]', ...args);
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
const logFn = (level, msg) => {
|
|
50
|
+
switch (level) {
|
|
51
|
+
case 'debug':
|
|
52
|
+
logger.debug(msg);
|
|
53
|
+
break;
|
|
54
|
+
case 'info':
|
|
55
|
+
logger.info(msg);
|
|
56
|
+
break;
|
|
57
|
+
case 'warn':
|
|
58
|
+
logger.warn(msg);
|
|
59
|
+
break;
|
|
60
|
+
case 'error':
|
|
61
|
+
logger.error(msg);
|
|
62
|
+
break;
|
|
63
|
+
default:
|
|
64
|
+
logger.info(msg);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
// Configure the simulator connection if provided
|
|
69
|
+
if (options.simulator) {
|
|
70
|
+
const cfg = {
|
|
71
|
+
simulatorApiUrl: options.simulator.apiUrl,
|
|
72
|
+
simulatorToken: options.simulator.token ?? options.token,
|
|
73
|
+
};
|
|
74
|
+
const res = await fetch(`${options.apiUrl}/simulator`, {
|
|
75
|
+
method: 'POST',
|
|
76
|
+
headers: {
|
|
77
|
+
'Content-Type': 'application/json',
|
|
78
|
+
Authorization: `Bearer ${options.token}`,
|
|
79
|
+
},
|
|
80
|
+
body: JSON.stringify(cfg),
|
|
81
|
+
});
|
|
82
|
+
const text = await res.text();
|
|
83
|
+
if (!res.ok) {
|
|
84
|
+
throw new Error(`POST /simulator failed: ${res.status} ${text}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
async sync(localCodePath, opts) {
|
|
89
|
+
const codeSyncOpts = {
|
|
90
|
+
apiUrl: options.apiUrl,
|
|
91
|
+
token: options.token,
|
|
92
|
+
udid: opts?.cacheKey ?? 'xcode-sandbox',
|
|
93
|
+
install: false,
|
|
94
|
+
filter: (relativePath) => {
|
|
95
|
+
if (relativePath.startsWith('build/') ||
|
|
96
|
+
relativePath.startsWith('.build/') ||
|
|
97
|
+
relativePath.startsWith('DerivedData/') ||
|
|
98
|
+
relativePath.startsWith('Index.noindex/') ||
|
|
99
|
+
relativePath.startsWith('ModuleCache.noindex/') ||
|
|
100
|
+
relativePath.startsWith('.index-build/')) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
if (relativePath.startsWith('.swiftpm/') ||
|
|
104
|
+
relativePath.startsWith('Pods/') ||
|
|
105
|
+
relativePath.startsWith('Carthage/Build/')) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
if (relativePath.startsWith('.git/') ||
|
|
109
|
+
relativePath.startsWith('.limsync-cache/') ||
|
|
110
|
+
relativePath === '.DS_Store' ||
|
|
111
|
+
relativePath.endsWith('/.DS_Store')) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
if (relativePath.includes('/xcuserdata/')) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
if (relativePath.includes('.dSYM/')) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
// User-provided filter
|
|
121
|
+
if (opts?.filter && !opts.filter(relativePath)) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
return true;
|
|
125
|
+
},
|
|
126
|
+
...(opts?.basisCacheDir ? { basisCacheDir: opts.basisCacheDir } : {}),
|
|
127
|
+
...(opts?.maxPatchBytes !== undefined ? { maxPatchBytes: opts.maxPatchBytes } : {}),
|
|
128
|
+
...(opts?.watch !== undefined ? { watch: opts.watch } : {}),
|
|
129
|
+
log: opts?.log ?? logFn,
|
|
130
|
+
};
|
|
131
|
+
const result = await syncFolderImpl(localCodePath, codeSyncOpts);
|
|
132
|
+
if (result.stopWatching) {
|
|
133
|
+
return { stopWatching: result.stopWatching };
|
|
134
|
+
}
|
|
135
|
+
return {};
|
|
136
|
+
},
|
|
137
|
+
xcodebuild(opts) {
|
|
138
|
+
return exec({ command: 'xcodebuild', ...(opts && { xcodebuild: opts }) }, {
|
|
139
|
+
apiUrl: options.apiUrl,
|
|
140
|
+
token: options.token,
|
|
141
|
+
log: logFn,
|
|
142
|
+
});
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=sandbox-client.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-client.mjs","sourceRoot":"","sources":["src/sandbox-client.ts"],"names":[],"mappings":"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"}
|
package/src/client.ts
CHANGED
|
@@ -537,9 +537,10 @@ export class Limrun {
|
|
|
537
537
|
controller: AbortController,
|
|
538
538
|
): Promise<Response> {
|
|
539
539
|
const { signal, method, ...options } = init || {};
|
|
540
|
-
|
|
540
|
+
const abort = this._makeAbort(controller);
|
|
541
|
+
if (signal) signal.addEventListener('abort', abort, { once: true });
|
|
541
542
|
|
|
542
|
-
const timeout = setTimeout(
|
|
543
|
+
const timeout = setTimeout(abort, ms);
|
|
543
544
|
|
|
544
545
|
const isReadableBody =
|
|
545
546
|
((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) ||
|
|
@@ -562,6 +563,7 @@ export class Limrun {
|
|
|
562
563
|
return await this.fetch.call(undefined, url, fetchOptions);
|
|
563
564
|
} finally {
|
|
564
565
|
clearTimeout(timeout);
|
|
566
|
+
if (signal) signal.removeEventListener('abort', abort);
|
|
565
567
|
}
|
|
566
568
|
}
|
|
567
569
|
|
|
@@ -706,6 +708,12 @@ export class Limrun {
|
|
|
706
708
|
return headers.values;
|
|
707
709
|
}
|
|
708
710
|
|
|
711
|
+
private _makeAbort(controller: AbortController) {
|
|
712
|
+
// note: we can't just inline this method inside `fetchWithTimeout()` because then the closure
|
|
713
|
+
// would capture all request options, and cause a memory leak.
|
|
714
|
+
return () => controller.abort();
|
|
715
|
+
}
|
|
716
|
+
|
|
709
717
|
private buildBody({ options: { body, headers: rawHeaders } }: { options: FinalRequestOptions }): {
|
|
710
718
|
bodyHeaders: HeadersLike;
|
|
711
719
|
body: BodyInit | undefined;
|