@limrun/api 0.28.1 → 0.28.3
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 +17 -0
- package/client.d.mts.map +1 -1
- package/client.d.ts.map +1 -1
- package/client.js +11 -0
- package/client.js.map +1 -1
- package/client.mjs +11 -0
- package/client.mjs.map +1 -1
- package/folder-sync-ignore.d.mts +2 -0
- package/folder-sync-ignore.d.mts.map +1 -1
- package/folder-sync-ignore.d.ts +2 -0
- package/folder-sync-ignore.d.ts.map +1 -1
- package/folder-sync-ignore.js +53 -2
- package/folder-sync-ignore.js.map +1 -1
- package/folder-sync-ignore.mjs +53 -2
- package/folder-sync-ignore.mjs.map +1 -1
- package/folder-sync.d.mts +9 -0
- package/folder-sync.d.mts.map +1 -1
- package/folder-sync.d.ts +9 -0
- package/folder-sync.d.ts.map +1 -1
- package/folder-sync.js +43 -7
- package/folder-sync.js.map +1 -1
- package/folder-sync.mjs +43 -7
- package/folder-sync.mjs.map +1 -1
- package/ios-client.d.mts.map +1 -1
- package/ios-client.d.ts.map +1 -1
- package/ios-client.js +21 -20
- package/ios-client.js.map +1 -1
- package/ios-client.mjs +21 -20
- package/ios-client.mjs.map +1 -1
- package/package.json +1 -1
- package/resources/xcode-instances-helpers.d.mts +8 -0
- package/resources/xcode-instances-helpers.d.mts.map +1 -1
- package/resources/xcode-instances-helpers.d.ts +8 -0
- package/resources/xcode-instances-helpers.d.ts.map +1 -1
- package/resources/xcode-instances-helpers.js +46 -1
- package/resources/xcode-instances-helpers.js.map +1 -1
- package/resources/xcode-instances-helpers.mjs +47 -2
- package/resources/xcode-instances-helpers.mjs.map +1 -1
- package/src/client.ts +12 -0
- package/src/folder-sync-ignore.ts +64 -2
- package/src/folder-sync.ts +60 -8
- package/src/ios-client.ts +21 -20
- package/src/resources/xcode-instances-helpers.ts +62 -3
- 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
|
@@ -3,7 +3,7 @@ import path from 'path';
|
|
|
3
3
|
import crypto from 'crypto';
|
|
4
4
|
import { XcodeInstances as GeneratedXcodeInstances } from "./xcode-instances.mjs";
|
|
5
5
|
import { exec } from "../exec-client.mjs";
|
|
6
|
-
import { syncFolder as syncFolderImpl } from "../folder-sync.mjs";
|
|
6
|
+
import { syncFolder as syncFolderImpl, } from "../folder-sync.mjs";
|
|
7
7
|
import { createIgnoreFn } from "../folder-sync-ignore.mjs";
|
|
8
8
|
import { nodeProxyTransport } from "../internal/proxy-transport.mjs";
|
|
9
9
|
function createLogger(logLevel) {
|
|
@@ -23,6 +23,38 @@ function createLogger(logLevel) {
|
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
+
function normalizeWorkspaceRelativePath(remotePath) {
|
|
27
|
+
if (remotePath === '' ||
|
|
28
|
+
remotePath.startsWith('/') ||
|
|
29
|
+
remotePath.includes('\\') ||
|
|
30
|
+
remotePath.includes('\0')) {
|
|
31
|
+
throw new Error(`invalid sandbox home path from server: ${remotePath}`);
|
|
32
|
+
}
|
|
33
|
+
const parts = remotePath.split('/');
|
|
34
|
+
if (parts.some((part) => part === '' || part === '.' || part === '..')) {
|
|
35
|
+
throw new Error(`invalid sandbox home path from server: ${remotePath}`);
|
|
36
|
+
}
|
|
37
|
+
return parts.join('/');
|
|
38
|
+
}
|
|
39
|
+
async function fetchSandboxInfo(apiUrl, token) {
|
|
40
|
+
const res = await nodeProxyTransport.fetch(`${apiUrl}/info`, {
|
|
41
|
+
method: 'GET',
|
|
42
|
+
headers: {
|
|
43
|
+
Authorization: `Bearer ${token}`,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
const text = await res.text();
|
|
47
|
+
if (!res.ok) {
|
|
48
|
+
throw new Error(`GET /info failed: ${res.status} ${text}`);
|
|
49
|
+
}
|
|
50
|
+
const body = JSON.parse(text);
|
|
51
|
+
if (!body.homeDir) {
|
|
52
|
+
throw new Error('GET /info response is missing homeDir');
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
homeDir: normalizeWorkspaceRelativePath(body.homeDir),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
26
58
|
export class XcodeInstances extends GeneratedXcodeInstances {
|
|
27
59
|
async createClient(params) {
|
|
28
60
|
let apiUrl;
|
|
@@ -40,6 +72,7 @@ export class XcodeInstances extends GeneratedXcodeInstances {
|
|
|
40
72
|
}
|
|
41
73
|
const log = createLogger(params.logLevel ?? 'info');
|
|
42
74
|
const client = this._client;
|
|
75
|
+
const sandboxInfo = await fetchSandboxInfo(apiUrl, token);
|
|
43
76
|
return {
|
|
44
77
|
async sync(localCodePath, opts) {
|
|
45
78
|
const resolvedPath = path.resolve(localCodePath);
|
|
@@ -47,6 +80,12 @@ export class XcodeInstances extends GeneratedXcodeInstances {
|
|
|
47
80
|
const hash = crypto.createHash('sha1').update(resolvedPath).digest('hex').slice(0, 8);
|
|
48
81
|
const cacheKey = `limsync-cache-${folderName}-${hash}`;
|
|
49
82
|
const basisCacheDir = opts?.basisCacheDir ?? path.join(os.tmpdir(), cacheKey);
|
|
83
|
+
const additionalFiles = opts?.additionalFiles?.map((file) => ({
|
|
84
|
+
localPath: file.localPath,
|
|
85
|
+
remotePath: file.remotePath.startsWith('~/') ?
|
|
86
|
+
`${sandboxInfo.homeDir}/${file.remotePath.slice(2)}`
|
|
87
|
+
: file.remotePath,
|
|
88
|
+
}));
|
|
50
89
|
const codeSyncOpts = {
|
|
51
90
|
apiUrl,
|
|
52
91
|
token,
|
|
@@ -54,6 +93,7 @@ export class XcodeInstances extends GeneratedXcodeInstances {
|
|
|
54
93
|
install: opts?.install ?? true,
|
|
55
94
|
ignoreFn: await createIgnoreFn(localCodePath, {
|
|
56
95
|
basisCacheDir,
|
|
96
|
+
log,
|
|
57
97
|
additional: (relativePath) => {
|
|
58
98
|
if (relativePath.startsWith('build/') ||
|
|
59
99
|
relativePath.startsWith('.build/') ||
|
|
@@ -85,6 +125,7 @@ export class XcodeInstances extends GeneratedXcodeInstances {
|
|
|
85
125
|
maxPatchBytes: opts?.maxPatchBytes ?? 4 * 1024 * 1024,
|
|
86
126
|
launchMode: 'ForegroundIfRunning',
|
|
87
127
|
log,
|
|
128
|
+
...(additionalFiles ? { additionalFiles } : {}),
|
|
88
129
|
};
|
|
89
130
|
const result = await syncFolderImpl(localCodePath, codeSyncOpts);
|
|
90
131
|
if (result.stopWatching) {
|
|
@@ -97,7 +138,7 @@ export class XcodeInstances extends GeneratedXcodeInstances {
|
|
|
97
138
|
command: 'xcodebuild',
|
|
98
139
|
...(settings && { xcodebuild: settings }),
|
|
99
140
|
};
|
|
100
|
-
if (options?.upload) {
|
|
141
|
+
if (options?.upload && 'assetName' in options.upload) {
|
|
101
142
|
const uploadName = options.upload.assetName;
|
|
102
143
|
const requestPromise = client.assets
|
|
103
144
|
.getOrCreate({ name: uploadName })
|
|
@@ -111,6 +152,10 @@ export class XcodeInstances extends GeneratedXcodeInstances {
|
|
|
111
152
|
});
|
|
112
153
|
return exec(requestPromise, { apiUrl, token, log });
|
|
113
154
|
}
|
|
155
|
+
if (options?.upload && 'signedUploadUrl' in options.upload && 'signedDownloadUrl' in options.upload) {
|
|
156
|
+
request.signedUploadUrl = options.upload.signedUploadUrl;
|
|
157
|
+
request.additionalMetadata = { signedDownloadUrl: options.upload.signedDownloadUrl };
|
|
158
|
+
}
|
|
114
159
|
return exec(request, { apiUrl, token, log });
|
|
115
160
|
},
|
|
116
161
|
async attachSimulator(simulator) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xcode-instances-helpers.mjs","sourceRoot":"","sources":["../src/resources/xcode-instances-helpers.ts"],"names":[],"mappings":"OAAO,EAAE,MAAM,IAAI;OACZ,IAAI,MAAM,MAAM;OAChB,MAAM,MAAM,QAAQ;OAEpB,EAAE,cAAc,IAAI,uBAAuB,EAAsB;OAEjE,EAAE,IAAI,EAA2C;OACjD,
|
|
1
|
+
{"version":3,"file":"xcode-instances-helpers.mjs","sourceRoot":"","sources":["../src/resources/xcode-instances-helpers.ts"],"names":[],"mappings":"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"}
|
package/src/client.ts
CHANGED
|
@@ -198,6 +198,18 @@ export class Limrun {
|
|
|
198
198
|
this.fetch = options.fetch ?? Shims.getDefaultFetch();
|
|
199
199
|
this.#encoder = Opts.FallbackEncoder;
|
|
200
200
|
|
|
201
|
+
const customHeadersEnv = readEnv('LIMRUN_CUSTOM_HEADERS');
|
|
202
|
+
if (customHeadersEnv) {
|
|
203
|
+
const parsed: Record<string, string> = {};
|
|
204
|
+
for (const line of customHeadersEnv.split('\n')) {
|
|
205
|
+
const colon = line.indexOf(':');
|
|
206
|
+
if (colon >= 0) {
|
|
207
|
+
parsed[line.substring(0, colon).trim()] = line.substring(colon + 1).trim();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
options.defaultHeaders = { ...parsed, ...options.defaultHeaders };
|
|
211
|
+
}
|
|
212
|
+
|
|
201
213
|
this._options = options;
|
|
202
214
|
|
|
203
215
|
this.apiKey = apiKey;
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { execFile } from 'child_process';
|
|
4
|
+
import { promisify } from 'util';
|
|
3
5
|
import ignorePkg from 'ignore';
|
|
4
6
|
|
|
7
|
+
const execFileAsync = promisify(execFile);
|
|
8
|
+
|
|
5
9
|
export type IgnoreFn = (relativePath: string) => boolean;
|
|
6
10
|
|
|
11
|
+
export type IgnoreLogger = (level: 'debug' | 'info' | 'warn' | 'error', msg: string) => void;
|
|
12
|
+
|
|
7
13
|
export type IgnoreFnOptions = {
|
|
8
14
|
additional?: IgnoreFn;
|
|
9
15
|
basisCacheDir: string;
|
|
16
|
+
log?: IgnoreLogger;
|
|
10
17
|
};
|
|
11
18
|
|
|
12
19
|
function normalizeRelativePath(relativePath: string): string {
|
|
@@ -17,9 +24,42 @@ function normalizeRelativePath(relativePath: string): string {
|
|
|
17
24
|
.replace(/\/+/g, '/');
|
|
18
25
|
}
|
|
19
26
|
|
|
27
|
+
type GitTrackedSets = {
|
|
28
|
+
tracked: Set<string>;
|
|
29
|
+
prefixes: Set<string>;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
async function getGitTrackedSets(rootDir: string): Promise<GitTrackedSets | null> {
|
|
33
|
+
try {
|
|
34
|
+
const { stdout } = await execFileAsync('git', ['ls-files', '-z'], {
|
|
35
|
+
cwd: rootDir,
|
|
36
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
37
|
+
});
|
|
38
|
+
const tracked = new Set<string>();
|
|
39
|
+
const prefixes = new Set<string>();
|
|
40
|
+
for (const file of stdout.split('\0')) {
|
|
41
|
+
if (!file) continue;
|
|
42
|
+
tracked.add(file);
|
|
43
|
+
let idx = file.lastIndexOf('/');
|
|
44
|
+
while (idx > 0) {
|
|
45
|
+
prefixes.add(file.substring(0, idx));
|
|
46
|
+
idx = file.lastIndexOf('/', idx - 1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { tracked, prefixes };
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
20
55
|
export async function createIgnoreFn(rootDir: string, options: IgnoreFnOptions): Promise<IgnoreFn> {
|
|
21
56
|
const rootResolved = path.resolve(rootDir);
|
|
22
|
-
|
|
57
|
+
// ignorecase: false matches git's default semantics. The package defaults to true,
|
|
58
|
+
// which silently drops e.g. `Vendor/` when .gitignore says `vendor/` (Ruby convention).
|
|
59
|
+
// allowRelativePaths: true so a `../`-style path doesn't throw mid-sync — treat it as
|
|
60
|
+
// "not ignored" and let it through, since the cost of dropping a needed file is higher
|
|
61
|
+
// than including an unexpected one.
|
|
62
|
+
const ig = ignorePkg({ ignorecase: false, allowRelativePaths: true });
|
|
23
63
|
const gitignorePath = path.join(rootResolved, '.gitignore');
|
|
24
64
|
try {
|
|
25
65
|
const content = await fs.promises.readFile(gitignorePath, 'utf-8');
|
|
@@ -36,6 +76,11 @@ export async function createIgnoreFn(rootDir: string, options: IgnoreFnOptions):
|
|
|
36
76
|
basisCacheRelative !== '..' &&
|
|
37
77
|
!basisCacheRelative.startsWith('../');
|
|
38
78
|
|
|
79
|
+
const trackedSets = await getGitTrackedSets(rootResolved);
|
|
80
|
+
const log = options.log;
|
|
81
|
+
// Dedupe by .gitignore rule so a single bad rule doesn't spam the log per matched file.
|
|
82
|
+
const warnedRules = new Set<string>();
|
|
83
|
+
|
|
39
84
|
return (relativePath: string) => {
|
|
40
85
|
const normalized = normalizeRelativePath(relativePath);
|
|
41
86
|
if (!normalized) return false;
|
|
@@ -59,7 +104,24 @@ export async function createIgnoreFn(rootDir: string, options: IgnoreFnOptions):
|
|
|
59
104
|
return true;
|
|
60
105
|
}
|
|
61
106
|
if (withoutTrailingSlash.endsWith('.xcconfig')) return false;
|
|
62
|
-
if (ig.ignores(normalized))
|
|
107
|
+
if (ig.ignores(normalized)) {
|
|
108
|
+
if (
|
|
109
|
+
trackedSets &&
|
|
110
|
+
(trackedSets.tracked.has(withoutTrailingSlash) || trackedSets.prefixes.has(withoutTrailingSlash))
|
|
111
|
+
) {
|
|
112
|
+
const rule = ig.test(normalized).rule?.pattern ?? '<unknown>';
|
|
113
|
+
if (!warnedRules.has(rule)) {
|
|
114
|
+
warnedRules.add(rule);
|
|
115
|
+
const msg = `.gitignore rule '${rule}' is dropping '${withoutTrailingSlash}', which is tracked in git. The remote build will not see this path. Remove or scope the rule if you need it synced.`;
|
|
116
|
+
if (log) {
|
|
117
|
+
log('warn', msg);
|
|
118
|
+
} else {
|
|
119
|
+
console.warn('[FolderSync]', msg);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
63
125
|
if (options.additional?.(normalized)) return true;
|
|
64
126
|
return false;
|
|
65
127
|
};
|
package/src/folder-sync.ts
CHANGED
|
@@ -47,6 +47,11 @@ export type FolderSyncOptions = {
|
|
|
47
47
|
* ignoreFn: (path) => !(path.startsWith('src/') || path.endsWith('.json'))
|
|
48
48
|
*/
|
|
49
49
|
ignoreFn: IgnoreFn;
|
|
50
|
+
/**
|
|
51
|
+
* Extra files to sync into limbuild. These are included
|
|
52
|
+
* in every sync pass but are not watched directly.
|
|
53
|
+
*/
|
|
54
|
+
additionalFiles?: AdditionalFileSyncEntry[];
|
|
50
55
|
};
|
|
51
56
|
|
|
52
57
|
export type SyncFolderResult = {
|
|
@@ -56,7 +61,15 @@ export type SyncFolderResult = {
|
|
|
56
61
|
stopWatching?: () => void;
|
|
57
62
|
};
|
|
58
63
|
|
|
59
|
-
type
|
|
64
|
+
export type AdditionalFileSyncEntry = { localPath: string; remotePath: string };
|
|
65
|
+
|
|
66
|
+
type FileEntry = {
|
|
67
|
+
path: string;
|
|
68
|
+
size: number;
|
|
69
|
+
sha256: string;
|
|
70
|
+
absPath: string;
|
|
71
|
+
mode: number;
|
|
72
|
+
};
|
|
60
73
|
|
|
61
74
|
type FolderSyncHttpPayload = {
|
|
62
75
|
kind: 'delta' | 'full';
|
|
@@ -284,6 +297,33 @@ async function walkFiles(root: string, ignoreFn: IgnoreFn): Promise<FileEntry[]>
|
|
|
284
297
|
return out;
|
|
285
298
|
}
|
|
286
299
|
|
|
300
|
+
async function collectAdditionalFiles(
|
|
301
|
+
additionalFiles: AdditionalFileSyncEntry[] | undefined,
|
|
302
|
+
): Promise<FileEntry[]> {
|
|
303
|
+
if (!additionalFiles || additionalFiles.length === 0) {
|
|
304
|
+
return [];
|
|
305
|
+
}
|
|
306
|
+
const out: FileEntry[] = [];
|
|
307
|
+
for (const additionalFile of additionalFiles) {
|
|
308
|
+
const remotePath = additionalFile.remotePath;
|
|
309
|
+
const absPath = path.resolve(additionalFile.localPath);
|
|
310
|
+
const st = await fs.promises.stat(absPath);
|
|
311
|
+
if (!st.isFile()) {
|
|
312
|
+
throw new Error(`additional file localPath must be a file: ${additionalFile.localPath}`);
|
|
313
|
+
}
|
|
314
|
+
const sha256 = await sha256FileHex(absPath);
|
|
315
|
+
out.push({
|
|
316
|
+
path: remotePath,
|
|
317
|
+
size: st.size,
|
|
318
|
+
sha256,
|
|
319
|
+
absPath,
|
|
320
|
+
mode: st.mode & 0o7777,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
out.sort((a, b) => a.path.localeCompare(b.path));
|
|
324
|
+
return out;
|
|
325
|
+
}
|
|
326
|
+
|
|
287
327
|
// xdelta3 encoder backed by a WASM build of the upstream xdelta3 library.
|
|
288
328
|
// Produces VCDIFF-compatible patches identical to `xdelta3 -e -s basis target`,
|
|
289
329
|
// so the server-side decoder continues to apply them without changes.
|
|
@@ -421,7 +461,9 @@ async function syncFolderOnce(
|
|
|
421
461
|
const maxPatchBytes = opts.maxPatchBytes ?? 4 * 1024 * 1024;
|
|
422
462
|
|
|
423
463
|
const files = await walkFiles(localFolderPath, opts.ignoreFn);
|
|
424
|
-
const
|
|
464
|
+
const additionalFiles = await collectAdditionalFiles(opts.additionalFiles);
|
|
465
|
+
const allFiles = [...files, ...additionalFiles].sort((a, b) => a.path.localeCompare(b.path));
|
|
466
|
+
const fileMap = new Map(allFiles.map((f) => [f.path, f]));
|
|
425
467
|
|
|
426
468
|
const syncId = genId('sync');
|
|
427
469
|
const rootName = path.basename(path.resolve(localFolderPath));
|
|
@@ -439,7 +481,7 @@ async function syncFolderOnce(
|
|
|
439
481
|
// Build payload list by comparing against local basis cache (single-flight/watch assumes server matches cache).
|
|
440
482
|
const encodeLimit = concurrencyLimit();
|
|
441
483
|
const changed: FileEntry[] = [];
|
|
442
|
-
for (const f of
|
|
484
|
+
for (const f of allFiles) {
|
|
443
485
|
const basisPath = cacheGet(opts.basisCacheDir, f.path);
|
|
444
486
|
if (!fs.existsSync(basisPath)) {
|
|
445
487
|
changed.push(f);
|
|
@@ -489,7 +531,12 @@ async function syncFolderOnce(
|
|
|
489
531
|
slog('debug', `full(file): ${f.path} size=${f.size}`);
|
|
490
532
|
bytesSentFull += f.size;
|
|
491
533
|
return {
|
|
492
|
-
payload: {
|
|
534
|
+
payload: {
|
|
535
|
+
kind: 'full',
|
|
536
|
+
path: f.path,
|
|
537
|
+
targetSha256: f.sha256.toLowerCase(),
|
|
538
|
+
length: f.size,
|
|
539
|
+
},
|
|
493
540
|
filePath: f.absPath,
|
|
494
541
|
};
|
|
495
542
|
});
|
|
@@ -499,14 +546,19 @@ async function syncFolderOnce(
|
|
|
499
546
|
rootName,
|
|
500
547
|
install: opts.install,
|
|
501
548
|
...(opts.launchMode ? { launchMode: opts.launchMode } : {}),
|
|
502
|
-
files:
|
|
549
|
+
files: allFiles.map((f) => ({
|
|
550
|
+
path: f.path,
|
|
551
|
+
size: f.size,
|
|
552
|
+
sha256: f.sha256.toLowerCase(),
|
|
553
|
+
mode: f.mode,
|
|
554
|
+
})),
|
|
503
555
|
payloads: encodedPayloads.map((p) => p.payload),
|
|
504
556
|
};
|
|
505
557
|
const hasDelta = encodedPayloads.some((p) => p.payload.kind === 'delta');
|
|
506
558
|
const compression: 'zstd' | 'gzip' | 'identity' = hasDelta ? 'identity' : preferredCompression;
|
|
507
559
|
slog(
|
|
508
560
|
'debug',
|
|
509
|
-
`sync started files=${
|
|
561
|
+
`sync started files=${allFiles.length}${reason ? ` reason=${reason}` : ''} compression=${compression}`,
|
|
510
562
|
);
|
|
511
563
|
|
|
512
564
|
const sendStart = nowMs();
|
|
@@ -583,7 +635,7 @@ async function syncFolderOnce(
|
|
|
583
635
|
const totalBytes = bytesSentFull + bytesSentDelta;
|
|
584
636
|
slog(
|
|
585
637
|
'debug',
|
|
586
|
-
`sync finished files=${
|
|
638
|
+
`sync finished files=${allFiles.length} sent=${fmtBytes(totalBytes)} syncWork=${fmtMs(
|
|
587
639
|
syncWorkMs,
|
|
588
640
|
)} total=${fmtMs(tookMs)}`,
|
|
589
641
|
);
|
|
@@ -595,7 +647,7 @@ async function syncFolderOnce(
|
|
|
595
647
|
out.installedBundleId = resp.bundleId;
|
|
596
648
|
}
|
|
597
649
|
// Update local cache optimistically: after a successful sync, cache reflects current local tree.
|
|
598
|
-
for (const f of
|
|
650
|
+
for (const f of allFiles) {
|
|
599
651
|
await cachePut(opts.basisCacheDir, f.path, f.absPath);
|
|
600
652
|
}
|
|
601
653
|
return out;
|
package/src/ios-client.ts
CHANGED
|
@@ -1763,31 +1763,32 @@ export async function createInstanceClient(options: InstanceClientOptions): Prom
|
|
|
1763
1763
|
const hash = crypto.createHash('sha1').update(resolvedPath).digest('hex').slice(0, 8);
|
|
1764
1764
|
const cacheKey = `limsync-cache-${folderName}-${hash}`;
|
|
1765
1765
|
const basisCacheDir = opts?.basisCacheDir ?? path.join(os.tmpdir(), cacheKey);
|
|
1766
|
+
const syncLog: FolderSyncOptions['log'] = (level, msg) => {
|
|
1767
|
+
switch (level) {
|
|
1768
|
+
case 'debug':
|
|
1769
|
+
logger.debug(msg);
|
|
1770
|
+
break;
|
|
1771
|
+
case 'info':
|
|
1772
|
+
logger.info(msg);
|
|
1773
|
+
break;
|
|
1774
|
+
case 'warn':
|
|
1775
|
+
logger.warn(msg);
|
|
1776
|
+
break;
|
|
1777
|
+
case 'error':
|
|
1778
|
+
logger.error(msg);
|
|
1779
|
+
break;
|
|
1780
|
+
default:
|
|
1781
|
+
logger.info(msg);
|
|
1782
|
+
break;
|
|
1783
|
+
}
|
|
1784
|
+
};
|
|
1766
1785
|
const folderSyncOpts: FolderSyncOptions = {
|
|
1767
1786
|
apiUrl: options.apiUrl,
|
|
1768
1787
|
token: options.token,
|
|
1769
1788
|
udid: cacheKey,
|
|
1770
|
-
ignoreFn: await createIgnoreFn(localAppBundlePath, { basisCacheDir }),
|
|
1789
|
+
ignoreFn: await createIgnoreFn(localAppBundlePath, { basisCacheDir, log: syncLog }),
|
|
1771
1790
|
basisCacheDir,
|
|
1772
|
-
log:
|
|
1773
|
-
switch (level) {
|
|
1774
|
-
case 'debug':
|
|
1775
|
-
logger.debug(msg);
|
|
1776
|
-
break;
|
|
1777
|
-
case 'info':
|
|
1778
|
-
logger.info(msg);
|
|
1779
|
-
break;
|
|
1780
|
-
case 'warn':
|
|
1781
|
-
logger.warn(msg);
|
|
1782
|
-
break;
|
|
1783
|
-
case 'error':
|
|
1784
|
-
logger.error(msg);
|
|
1785
|
-
break;
|
|
1786
|
-
default:
|
|
1787
|
-
logger.info(msg);
|
|
1788
|
-
break;
|
|
1789
|
-
}
|
|
1790
|
-
},
|
|
1791
|
+
log: syncLog,
|
|
1791
1792
|
install: opts?.install ?? true,
|
|
1792
1793
|
maxPatchBytes: opts?.maxPatchBytes ?? 4 * 1024 * 1024,
|
|
1793
1794
|
launchMode: opts?.launchMode ?? 'ForegroundIfRunning',
|
|
@@ -5,7 +5,11 @@ import crypto from 'crypto';
|
|
|
5
5
|
import { XcodeInstances as GeneratedXcodeInstances, type XcodeInstance } from './xcode-instances';
|
|
6
6
|
import { type IosInstance } from './ios-instances';
|
|
7
7
|
import { exec, type ExecChildProcess, type ExecRequest } from '../exec-client';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
syncFolder as syncFolderImpl,
|
|
10
|
+
type AdditionalFileSyncEntry,
|
|
11
|
+
type FolderSyncOptions,
|
|
12
|
+
} from '../folder-sync';
|
|
9
13
|
import { createIgnoreFn } from '../folder-sync-ignore';
|
|
10
14
|
import { nodeProxyTransport } from '../internal/proxy-transport';
|
|
11
15
|
|
|
@@ -32,6 +36,10 @@ export type SyncOptions = {
|
|
|
32
36
|
* Return true to ignore, false to keep.
|
|
33
37
|
*/
|
|
34
38
|
ignore?: (relativePath: string) => boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Extra files to sync on every sync pass.
|
|
41
|
+
*/
|
|
42
|
+
additionalFiles?: AdditionalFileSyncEntry[];
|
|
35
43
|
};
|
|
36
44
|
|
|
37
45
|
export type SyncResult = {
|
|
@@ -47,7 +55,7 @@ export type XcodeProjectConfig = {
|
|
|
47
55
|
};
|
|
48
56
|
|
|
49
57
|
export type XcodeBuildOptions = {
|
|
50
|
-
upload?: { assetName: string };
|
|
58
|
+
upload?: { assetName: string } | { signedUploadUrl: string; signedDownloadUrl: string };
|
|
51
59
|
};
|
|
52
60
|
|
|
53
61
|
export type XcodeClient = {
|
|
@@ -94,6 +102,42 @@ function createLogger(logLevel: LogLevel) {
|
|
|
94
102
|
};
|
|
95
103
|
}
|
|
96
104
|
|
|
105
|
+
function normalizeWorkspaceRelativePath(remotePath: string): string {
|
|
106
|
+
if (
|
|
107
|
+
remotePath === '' ||
|
|
108
|
+
remotePath.startsWith('/') ||
|
|
109
|
+
remotePath.includes('\\') ||
|
|
110
|
+
remotePath.includes('\0')
|
|
111
|
+
) {
|
|
112
|
+
throw new Error(`invalid sandbox home path from server: ${remotePath}`);
|
|
113
|
+
}
|
|
114
|
+
const parts = remotePath.split('/');
|
|
115
|
+
if (parts.some((part) => part === '' || part === '.' || part === '..')) {
|
|
116
|
+
throw new Error(`invalid sandbox home path from server: ${remotePath}`);
|
|
117
|
+
}
|
|
118
|
+
return parts.join('/');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function fetchSandboxInfo(apiUrl: string, token: string): Promise<{ homeDir: string }> {
|
|
122
|
+
const res = await nodeProxyTransport.fetch(`${apiUrl}/info`, {
|
|
123
|
+
method: 'GET',
|
|
124
|
+
headers: {
|
|
125
|
+
Authorization: `Bearer ${token}`,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
const text = await res.text();
|
|
129
|
+
if (!res.ok) {
|
|
130
|
+
throw new Error(`GET /info failed: ${res.status} ${text}`);
|
|
131
|
+
}
|
|
132
|
+
const body = JSON.parse(text) as { homeDir?: string };
|
|
133
|
+
if (!body.homeDir) {
|
|
134
|
+
throw new Error('GET /info response is missing homeDir');
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
homeDir: normalizeWorkspaceRelativePath(body.homeDir),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
97
141
|
export class XcodeInstances extends GeneratedXcodeInstances {
|
|
98
142
|
async createClient(params: XcodeCreateClientParams): Promise<XcodeClient> {
|
|
99
143
|
let apiUrl: string;
|
|
@@ -111,6 +155,7 @@ export class XcodeInstances extends GeneratedXcodeInstances {
|
|
|
111
155
|
|
|
112
156
|
const log = createLogger(params.logLevel ?? 'info');
|
|
113
157
|
const client = this._client;
|
|
158
|
+
const sandboxInfo = await fetchSandboxInfo(apiUrl, token);
|
|
114
159
|
|
|
115
160
|
return {
|
|
116
161
|
async sync(localCodePath: string, opts?: SyncOptions): Promise<SyncResult> {
|
|
@@ -119,6 +164,13 @@ export class XcodeInstances extends GeneratedXcodeInstances {
|
|
|
119
164
|
const hash = crypto.createHash('sha1').update(resolvedPath).digest('hex').slice(0, 8);
|
|
120
165
|
const cacheKey = `limsync-cache-${folderName}-${hash}`;
|
|
121
166
|
const basisCacheDir = opts?.basisCacheDir ?? path.join(os.tmpdir(), cacheKey);
|
|
167
|
+
const additionalFiles = opts?.additionalFiles?.map((file) => ({
|
|
168
|
+
localPath: file.localPath,
|
|
169
|
+
remotePath:
|
|
170
|
+
file.remotePath.startsWith('~/') ?
|
|
171
|
+
`${sandboxInfo.homeDir}/${file.remotePath.slice(2)}`
|
|
172
|
+
: file.remotePath,
|
|
173
|
+
}));
|
|
122
174
|
const codeSyncOpts: FolderSyncOptions = {
|
|
123
175
|
apiUrl,
|
|
124
176
|
token,
|
|
@@ -126,6 +178,7 @@ export class XcodeInstances extends GeneratedXcodeInstances {
|
|
|
126
178
|
install: opts?.install ?? true,
|
|
127
179
|
ignoreFn: await createIgnoreFn(localCodePath, {
|
|
128
180
|
basisCacheDir,
|
|
181
|
+
log,
|
|
129
182
|
additional: (relativePath: string) => {
|
|
130
183
|
if (
|
|
131
184
|
relativePath.startsWith('build/') ||
|
|
@@ -161,6 +214,7 @@ export class XcodeInstances extends GeneratedXcodeInstances {
|
|
|
161
214
|
maxPatchBytes: opts?.maxPatchBytes ?? 4 * 1024 * 1024,
|
|
162
215
|
launchMode: 'ForegroundIfRunning',
|
|
163
216
|
log,
|
|
217
|
+
...(additionalFiles ? { additionalFiles } : {}),
|
|
164
218
|
};
|
|
165
219
|
|
|
166
220
|
const result = await syncFolderImpl(localCodePath, codeSyncOpts);
|
|
@@ -176,7 +230,7 @@ export class XcodeInstances extends GeneratedXcodeInstances {
|
|
|
176
230
|
...(settings && { xcodebuild: settings }),
|
|
177
231
|
};
|
|
178
232
|
|
|
179
|
-
if (options?.upload) {
|
|
233
|
+
if (options?.upload && 'assetName' in options.upload) {
|
|
180
234
|
const uploadName = options.upload.assetName;
|
|
181
235
|
const requestPromise = client.assets
|
|
182
236
|
.getOrCreate({ name: uploadName })
|
|
@@ -195,6 +249,11 @@ export class XcodeInstances extends GeneratedXcodeInstances {
|
|
|
195
249
|
return exec(requestPromise, { apiUrl, token, log });
|
|
196
250
|
}
|
|
197
251
|
|
|
252
|
+
if (options?.upload && 'signedUploadUrl' in options.upload && 'signedDownloadUrl' in options.upload) {
|
|
253
|
+
request.signedUploadUrl = options.upload.signedUploadUrl;
|
|
254
|
+
request.additionalMetadata = { signedDownloadUrl: options.upload.signedDownloadUrl };
|
|
255
|
+
}
|
|
256
|
+
|
|
198
257
|
return exec(request, { apiUrl, token, log });
|
|
199
258
|
},
|
|
200
259
|
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.28.
|
|
1
|
+
export const VERSION = '0.28.3'; // x-release-please-version
|
package/version.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.28.
|
|
1
|
+
export declare const VERSION = "0.28.3";
|
|
2
2
|
//# sourceMappingURL=version.d.mts.map
|
package/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.28.
|
|
1
|
+
export declare const VERSION = "0.28.3";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/version.js
CHANGED
package/version.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = '0.28.
|
|
1
|
+
export const VERSION = '0.28.3'; // x-release-please-version
|
|
2
2
|
//# sourceMappingURL=version.mjs.map
|