@leonxin/meetgames 0.1.15 → 0.1.17
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/config/meetsdk-ios.json +2 -2
- package/dist/cache.d.ts +1 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +1 -1
- package/dist/cache.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +16 -17
- package/dist/cli.js.map +1 -1
- package/dist/core/pipeline.js +1 -1
- package/dist/core/pipeline.js.map +1 -1
- package/dist/ios/fileManager.js +2 -2
- package/dist/ios/fileManager.js.map +1 -1
- package/dist/ios/integrate.d.ts.map +1 -1
- package/dist/ios/integrate.js +0 -1
- package/dist/ios/integrate.js.map +1 -1
- package/dist/ios/pbxprojEditor.d.ts.map +1 -1
- package/dist/ios/pbxprojEditor.js +45 -32
- package/dist/ios/pbxprojEditor.js.map +1 -1
- package/dist/remote/sdkHomeDownload.d.ts +4 -3
- package/dist/remote/sdkHomeDownload.d.ts.map +1 -1
- package/dist/remote/sdkHomeDownload.js +103 -26
- package/dist/remote/sdkHomeDownload.js.map +1 -1
- package/package.json +1 -1
- package/src/cache.ts +2 -1
- package/src/cli.ts +13 -17
- package/src/core/pipeline.ts +1 -1
- package/src/ios/fileManager.ts +2 -2
- package/src/ios/integrate.ts +0 -1
- package/src/ios/pbxprojEditor.ts +48 -32
- package/src/remote/sdkHomeDownload.ts +109 -29
- package/tests/pipeline.ios.test.ts +19 -0
- package/tests/sdkHomeDownload.test.ts +100 -0
package/src/ios/pbxprojEditor.ts
CHANGED
|
@@ -12,6 +12,13 @@ const xcode = require("xcode") as {
|
|
|
12
12
|
project: (pbxprojPath: string) => XcodeProject;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
const EXPECTED_SIGNATURE_BY_XCFRAMEWORK: Record<string, string> = {
|
|
16
|
+
"FBAEMKit.xcframework": '"AppleDeveloperProgram:V9WTTPBFK9:Meta Platforms, Inc."',
|
|
17
|
+
"FBSDKCoreKit.xcframework": '"AppleDeveloperProgram:V9WTTPBFK9:Meta Platforms, Inc."',
|
|
18
|
+
"FBSDKCoreKit_Basics.xcframework": '"AppleDeveloperProgram:V9WTTPBFK9:Meta Platforms, Inc."',
|
|
19
|
+
"FBSDKLoginKit.xcframework": '"AppleDeveloperProgram:V9WTTPBFK9:Meta Platforms, Inc."',
|
|
20
|
+
};
|
|
21
|
+
|
|
15
22
|
export interface PbxContext {
|
|
16
23
|
rel: string;
|
|
17
24
|
proj: XcodeProject;
|
|
@@ -216,6 +223,36 @@ function frameworkFileType(file: string): string {
|
|
|
216
223
|
return file.endsWith(".xcframework") ? "wrapper.xcframework" : "wrapper.framework";
|
|
217
224
|
}
|
|
218
225
|
|
|
226
|
+
function expectedSignature(file: string): string | undefined {
|
|
227
|
+
return EXPECTED_SIGNATURE_BY_XCFRAMEWORK[path.basename(file)];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function formatLastKnownFileType(lastKnownFileType: string): string {
|
|
231
|
+
return lastKnownFileType === "wrapper.plug-in" ? '"wrapper.plug-in"' : quotePbxStringIfNeeded(lastKnownFileType);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function topSdkFileReference(file: string, lastKnownFileType: string): Record<string, unknown> {
|
|
235
|
+
const basename = path.basename(file);
|
|
236
|
+
const ref: Record<string, unknown> = {
|
|
237
|
+
isa: "PBXFileReference",
|
|
238
|
+
};
|
|
239
|
+
const signature = expectedSignature(file);
|
|
240
|
+
if (signature) ref.expectedSignature = signature;
|
|
241
|
+
ref.lastKnownFileType = formatLastKnownFileType(lastKnownFileType);
|
|
242
|
+
ref.name = basename;
|
|
243
|
+
ref.path = file;
|
|
244
|
+
ref.sourceTree = "SOURCE_ROOT";
|
|
245
|
+
return ref;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function normalizeTopSdkFileReference(ref: Record<string, unknown>, file: string, lastKnownFileType: string): void {
|
|
249
|
+
const normalized = topSdkFileReference(file, lastKnownFileType);
|
|
250
|
+
for (const [key, value] of Object.entries(normalized)) {
|
|
251
|
+
ref[key] = value;
|
|
252
|
+
}
|
|
253
|
+
delete ref.includeInIndex;
|
|
254
|
+
}
|
|
255
|
+
|
|
219
256
|
function ensureFileRef(ctx: PbxContext, file: string, lastKnownFileType: string): string {
|
|
220
257
|
const basename = path.basename(file);
|
|
221
258
|
const existing = findFileRefUuid(ctx, file);
|
|
@@ -223,20 +260,13 @@ function ensureFileRef(ctx: PbxContext, file: string, lastKnownFileType: string)
|
|
|
223
260
|
if (existing) {
|
|
224
261
|
const ref = fileRefSection[existing];
|
|
225
262
|
if (ref && typeof ref === "object") {
|
|
226
|
-
(ref as Record<string, unknown
|
|
263
|
+
normalizeTopSdkFileReference(ref as Record<string, unknown>, file, lastKnownFileType);
|
|
227
264
|
}
|
|
228
265
|
return existing;
|
|
229
266
|
}
|
|
230
267
|
|
|
231
268
|
const uuid = ctx.proj.generateUuid();
|
|
232
|
-
fileRefSection[uuid] =
|
|
233
|
-
isa: "PBXFileReference",
|
|
234
|
-
name: `"${basename}"`,
|
|
235
|
-
path: `"${file}"`,
|
|
236
|
-
sourceTree: '"<group>"',
|
|
237
|
-
lastKnownFileType,
|
|
238
|
-
includeInIndex: 0,
|
|
239
|
-
};
|
|
269
|
+
fileRefSection[uuid] = topSdkFileReference(file, lastKnownFileType);
|
|
240
270
|
fileRefSection[`${uuid}_comment`] = basename;
|
|
241
271
|
return uuid;
|
|
242
272
|
}
|
|
@@ -322,15 +352,14 @@ function addCopyFileManually(ctx: PbxContext, target: string, file: string): voi
|
|
|
322
352
|
if (!fileRefUuid) {
|
|
323
353
|
fileRefUuid = ctx.proj.generateUuid();
|
|
324
354
|
const fileRefSection = objectSection(ctx.proj, "PBXFileReference");
|
|
325
|
-
fileRefSection[fileRefUuid] =
|
|
326
|
-
isa: "PBXFileReference",
|
|
327
|
-
name: `"${basename}"`,
|
|
328
|
-
path: `"${file}"`,
|
|
329
|
-
sourceTree: '"<group>"',
|
|
330
|
-
lastKnownFileType: "wrapper.framework",
|
|
331
|
-
includeInIndex: 0,
|
|
332
|
-
};
|
|
355
|
+
fileRefSection[fileRefUuid] = topSdkFileReference(file, "wrapper.framework");
|
|
333
356
|
fileRefSection[`${fileRefUuid}_comment`] = basename;
|
|
357
|
+
} else {
|
|
358
|
+
const fileRefSection = objectSection(ctx.proj, "PBXFileReference");
|
|
359
|
+
const ref = fileRefSection[fileRefUuid];
|
|
360
|
+
if (ref && typeof ref === "object") {
|
|
361
|
+
normalizeTopSdkFileReference(ref as Record<string, unknown>, file, "wrapper.framework");
|
|
362
|
+
}
|
|
334
363
|
}
|
|
335
364
|
|
|
336
365
|
const buildUuid = ctx.proj.generateUuid();
|
|
@@ -421,13 +450,7 @@ function addSourceFileManually(ctx: PbxContext, file: string, lastKnownFileType?
|
|
|
421
450
|
const fileRefSection = objectSection(ctx.proj, "PBXFileReference");
|
|
422
451
|
const buildFileSection = objectSection(ctx.proj, "PBXBuildFile");
|
|
423
452
|
|
|
424
|
-
fileRefSection[fileRefUuid] =
|
|
425
|
-
isa: "PBXFileReference",
|
|
426
|
-
name: `"${basename}"`,
|
|
427
|
-
path: `"${file}"`,
|
|
428
|
-
sourceTree: '"<group>"',
|
|
429
|
-
lastKnownFileType: lastKnownFileType ?? sourceFileType(file),
|
|
430
|
-
};
|
|
453
|
+
fileRefSection[fileRefUuid] = topSdkFileReference(file, lastKnownFileType ?? sourceFileType(file));
|
|
431
454
|
fileRefSection[`${fileRefUuid}_comment`] = basename;
|
|
432
455
|
buildFileSection[buildUuid] = {
|
|
433
456
|
isa: "PBXBuildFile",
|
|
@@ -458,14 +481,7 @@ function addResourceFileManually(ctx: PbxContext, file: string, lastKnownFileTyp
|
|
|
458
481
|
const fileRefSection = objectSection(ctx.proj, "PBXFileReference");
|
|
459
482
|
const buildFileSection = objectSection(ctx.proj, "PBXBuildFile");
|
|
460
483
|
|
|
461
|
-
fileRefSection[fileRefUuid] =
|
|
462
|
-
isa: "PBXFileReference",
|
|
463
|
-
name: `"${basename}"`,
|
|
464
|
-
path: `"${file}"`,
|
|
465
|
-
sourceTree: '"<group>"',
|
|
466
|
-
lastKnownFileType: resourceFileType(file, lastKnownFileType),
|
|
467
|
-
includeInIndex: 0,
|
|
468
|
-
};
|
|
484
|
+
fileRefSection[fileRefUuid] = topSdkFileReference(file, resourceFileType(file, lastKnownFileType));
|
|
469
485
|
fileRefSection[`${fileRefUuid}_comment`] = basename;
|
|
470
486
|
buildFileSection[buildUuid] = {
|
|
471
487
|
isa: "PBXBuildFile",
|
|
@@ -33,9 +33,9 @@ export interface SdkHomeDownloadUrlRequest {
|
|
|
33
33
|
|
|
34
34
|
export interface DownloadIosSdkOptions {
|
|
35
35
|
baseUrl?: string;
|
|
36
|
-
version?: string;
|
|
37
36
|
plugins?: readonly string[] | string;
|
|
38
37
|
packageType?: string;
|
|
38
|
+
cacheRoot?: string;
|
|
39
39
|
signal?: AbortSignal;
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -43,13 +43,14 @@ export interface DownloadIosSdkResult {
|
|
|
43
43
|
version: string;
|
|
44
44
|
versionDate: string;
|
|
45
45
|
versionUrl: string;
|
|
46
|
-
downloadApiUrl
|
|
47
|
-
sdkZipUrl
|
|
46
|
+
downloadApiUrl?: string;
|
|
47
|
+
sdkZipUrl?: string;
|
|
48
48
|
zipPath: string;
|
|
49
49
|
extractDir: string;
|
|
50
50
|
resolvedSdkRoot: string;
|
|
51
51
|
iosConfigPath: string;
|
|
52
52
|
cacheMetadataPath: string;
|
|
53
|
+
downloaded: boolean;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
function isRecord(value: unknown): value is JsonRecord {
|
|
@@ -188,6 +189,68 @@ export function resolveIosSdkRootFromDirectory(bundledDir: string): string {
|
|
|
188
189
|
throw new Error(`iOS SDK layout invalid under ${bundledDir}: need sdk/ + plugins/ at top level or under one version directory.`);
|
|
189
190
|
}
|
|
190
191
|
|
|
192
|
+
function tryResolveIosSdkRootFromDirectory(bundledDir: string): string | null {
|
|
193
|
+
try {
|
|
194
|
+
return resolveIosSdkRootFromDirectory(bundledDir);
|
|
195
|
+
} catch {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function compareSdkVersions(a: string, b: string): number {
|
|
201
|
+
const left = a.split(/[.-]/);
|
|
202
|
+
const right = b.split(/[.-]/);
|
|
203
|
+
const len = Math.max(left.length, right.length);
|
|
204
|
+
for (let i = 0; i < len; i += 1) {
|
|
205
|
+
const l = left[i] ?? "0";
|
|
206
|
+
const r = right[i] ?? "0";
|
|
207
|
+
const ln = /^\d+$/.test(l) ? Number(l) : null;
|
|
208
|
+
const rn = /^\d+$/.test(r) ? Number(r) : null;
|
|
209
|
+
if (ln !== null && rn !== null) {
|
|
210
|
+
if (ln !== rn) return ln - rn;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const cmp = l.localeCompare(r);
|
|
214
|
+
if (cmp !== 0) return cmp;
|
|
215
|
+
}
|
|
216
|
+
return 0;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function findReusableCachedIosSdk(params: {
|
|
220
|
+
cacheRoot?: string;
|
|
221
|
+
packageType: string;
|
|
222
|
+
plugins: readonly string[];
|
|
223
|
+
serverVersion: string;
|
|
224
|
+
}): { version: string; layout: ReturnType<typeof resolveIosSdkCacheLayout>; resolvedSdkRoot: string } | null {
|
|
225
|
+
const probe = resolveIosSdkCacheLayout({
|
|
226
|
+
version: "__probe__",
|
|
227
|
+
packageType: params.packageType,
|
|
228
|
+
plugins: params.plugins,
|
|
229
|
+
cacheRoot: params.cacheRoot,
|
|
230
|
+
});
|
|
231
|
+
const packageDir = path.dirname(path.dirname(probe.baseDir));
|
|
232
|
+
if (!fs.existsSync(packageDir)) return null;
|
|
233
|
+
|
|
234
|
+
let best: { version: string; layout: ReturnType<typeof resolveIosSdkCacheLayout>; resolvedSdkRoot: string } | null = null;
|
|
235
|
+
for (const ent of fs.readdirSync(packageDir, { withFileTypes: true })) {
|
|
236
|
+
if (!ent.isDirectory() || ent.name.startsWith(".")) continue;
|
|
237
|
+
const comparedToServer = compareSdkVersions(ent.name, params.serverVersion);
|
|
238
|
+
if (comparedToServer < 0) continue;
|
|
239
|
+
const layout = resolveIosSdkCacheLayout({
|
|
240
|
+
version: ent.name,
|
|
241
|
+
packageType: params.packageType,
|
|
242
|
+
plugins: params.plugins,
|
|
243
|
+
cacheRoot: params.cacheRoot,
|
|
244
|
+
});
|
|
245
|
+
const resolvedSdkRoot = tryResolveIosSdkRootFromDirectory(layout.extractDir);
|
|
246
|
+
if (!resolvedSdkRoot) continue;
|
|
247
|
+
if (!best || compareSdkVersions(ent.name, best.version) > 0) {
|
|
248
|
+
best = { version: ent.name, layout, resolvedSdkRoot };
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return best;
|
|
252
|
+
}
|
|
253
|
+
|
|
191
254
|
export async function downloadBinaryFile(url: string, absPath: string, signal?: AbortSignal): Promise<void> {
|
|
192
255
|
let res: Response;
|
|
193
256
|
try {
|
|
@@ -236,25 +299,39 @@ export async function downloadIosSdkToBundled(
|
|
|
236
299
|
const baseUrl = options.baseUrl || defaultSdkHomeApiBaseUrl;
|
|
237
300
|
const packageType = options.packageType || DEFAULT_IOS_SDK_PACKAGE_TYPE;
|
|
238
301
|
const plugins = pluginsToList(options.plugins);
|
|
239
|
-
const versionResult = options.
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const downloadResult = await fetchSdkHomeIosDownloadUrl({
|
|
244
|
-
baseUrl,
|
|
245
|
-
version,
|
|
246
|
-
plugins,
|
|
302
|
+
const versionResult = await fetchSdkHomeIosVersion({ baseUrl, signal: options.signal });
|
|
303
|
+
const serverVersion = versionResult.ios.ver;
|
|
304
|
+
const reusableCache = findReusableCachedIosSdk({
|
|
305
|
+
cacheRoot: options.cacheRoot,
|
|
247
306
|
packageType,
|
|
248
|
-
|
|
307
|
+
plugins,
|
|
308
|
+
serverVersion,
|
|
249
309
|
});
|
|
250
|
-
const
|
|
310
|
+
const version = reusableCache?.version ?? serverVersion;
|
|
311
|
+
const cacheLayout =
|
|
312
|
+
reusableCache?.layout ?? resolveIosSdkCacheLayout({ version, packageType, plugins, cacheRoot: options.cacheRoot });
|
|
251
313
|
const extractDir = cacheLayout.extractDir;
|
|
252
314
|
const zipPath = cacheLayout.zipPath;
|
|
315
|
+
let downloadApiUrl: string | undefined;
|
|
316
|
+
let sdkZipUrl: string | undefined;
|
|
317
|
+
let downloaded = false;
|
|
253
318
|
|
|
254
319
|
const downloadAndExtract = async (): Promise<void> => {
|
|
255
|
-
|
|
320
|
+
const cachedRoot = tryResolveIosSdkRootFromDirectory(extractDir);
|
|
321
|
+
if (cachedRoot) return;
|
|
322
|
+
const fetchedDownload = await fetchSdkHomeIosDownloadUrl({
|
|
323
|
+
baseUrl,
|
|
324
|
+
version,
|
|
325
|
+
plugins,
|
|
326
|
+
packageType,
|
|
327
|
+
signal: options.signal,
|
|
328
|
+
});
|
|
329
|
+
downloadApiUrl = fetchedDownload.url;
|
|
330
|
+
sdkZipUrl = fetchedDownload.sdkZipUrl;
|
|
331
|
+
await downloadBinaryFile(fetchedDownload.sdkZipUrl, zipPath, options.signal);
|
|
256
332
|
fs.rmSync(extractDir, { recursive: true, force: true });
|
|
257
333
|
await extractZip(zipPath, extractDir);
|
|
334
|
+
downloaded = true;
|
|
258
335
|
};
|
|
259
336
|
await withCacheLock(cacheLayout.lockDir, downloadAndExtract);
|
|
260
337
|
const iosConfigPath = syncMeetSdkIosVersionToConfig({
|
|
@@ -266,30 +343,33 @@ export async function downloadIosSdkToBundled(
|
|
|
266
343
|
});
|
|
267
344
|
const resolvedSdkRoot = resolveIosSdkRootFromDirectory(extractDir);
|
|
268
345
|
const cacheMetadataPath = cacheLayout.metadataPath;
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
346
|
+
if (downloaded && downloadApiUrl && sdkZipUrl) {
|
|
347
|
+
writeIosSdkCacheMetadata({
|
|
348
|
+
metadataPath: cacheMetadataPath,
|
|
349
|
+
version,
|
|
350
|
+
date: versionResult.ios.date,
|
|
351
|
+
packageType,
|
|
352
|
+
plugins,
|
|
353
|
+
versionUrl: versionResult.url,
|
|
354
|
+
downloadApiUrl,
|
|
355
|
+
sdkZipUrl,
|
|
356
|
+
zipPath,
|
|
357
|
+
extractDir,
|
|
358
|
+
resolvedSdkRoot,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
282
361
|
|
|
283
362
|
return {
|
|
284
363
|
version,
|
|
285
364
|
versionDate: versionResult.ios.date,
|
|
286
365
|
versionUrl: versionResult.url,
|
|
287
|
-
downloadApiUrl
|
|
288
|
-
sdkZipUrl
|
|
366
|
+
downloadApiUrl,
|
|
367
|
+
sdkZipUrl,
|
|
289
368
|
zipPath,
|
|
290
369
|
extractDir,
|
|
291
370
|
resolvedSdkRoot,
|
|
292
371
|
iosConfigPath,
|
|
293
372
|
cacheMetadataPath,
|
|
373
|
+
downloaded,
|
|
294
374
|
};
|
|
295
375
|
}
|
|
@@ -159,6 +159,18 @@ describe.skipIf(!hasIosProjectFixture)("pipeline ios fixture", () => {
|
|
|
159
159
|
expect(fs.existsSync(path.join(tmp, "topSDK", "TOPIAPPayPlugin.framework"))).toBe(true);
|
|
160
160
|
expect(fs.readFileSync(path.join(tmp, "topSDK", "TopSDKInstall.swift"), "utf8")).toBe("");
|
|
161
161
|
expect(fs.existsSync(path.join(tmp, "topSDK", "TopSDKSource.bundle"))).toBe(true);
|
|
162
|
+
expect(
|
|
163
|
+
fs.readlinkSync(
|
|
164
|
+
path.join(
|
|
165
|
+
tmp,
|
|
166
|
+
"topSDK",
|
|
167
|
+
"FBSDKLoginKit.xcframework",
|
|
168
|
+
"ios-arm64_x86_64-maccatalyst",
|
|
169
|
+
"FBSDKLoginKit.framework",
|
|
170
|
+
"FBSDKLoginKit"
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
).toBe("Versions/Current/FBSDKLoginKit");
|
|
162
174
|
|
|
163
175
|
const pbx = fs.readFileSync(path.join(tmp, "native-sample.xcodeproj", "project.pbxproj"), "utf8");
|
|
164
176
|
expect(pbx).toContain("TOPCore.framework");
|
|
@@ -167,6 +179,13 @@ describe.skipIf(!hasIosProjectFixture)("pipeline ios fixture", () => {
|
|
|
167
179
|
expect(pbx).toContain("TOPCoreModel.xcdatamodeld in Sources");
|
|
168
180
|
expect(pbx).not.toContain("TOPCoreModel.xcdatamodeld in Resources");
|
|
169
181
|
expect(pbx).not.toContain("FBSDKLoginKit.xcframework in Resources");
|
|
182
|
+
expect(pbx).toContain(
|
|
183
|
+
'FBSDKLoginKit.xcframework */ = {isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:V9WTTPBFK9:Meta Platforms, Inc."; lastKnownFileType = wrapper.xcframework; name = FBSDKLoginKit.xcframework; path = topSDK/FBSDKLoginKit.xcframework; sourceTree = SOURCE_ROOT; };'
|
|
184
|
+
);
|
|
185
|
+
expect(pbx).toContain("FBSDKCoreKit.xcframework");
|
|
186
|
+
expect(pbx).toContain("FBSDKCoreKit_Basics.xcframework");
|
|
187
|
+
expect(pbx).toContain("FBAEMKit.xcframework");
|
|
188
|
+
expect(pbx).not.toContain('path = "topSDK/FBSDKLoginKit.xcframework"; sourceTree = "<group>";');
|
|
170
189
|
expect(pbx).toContain("LIBRARY_SEARCH_PATHS = \"$(SRCROOT)/topSDK\"");
|
|
171
190
|
expect(pbx).toContain("SWIFT_VERSION = 5.0");
|
|
172
191
|
expect(pbx).toContain('"-ObjC"');
|
|
@@ -2,16 +2,19 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
5
6
|
import {
|
|
6
7
|
DEFAULT_IOS_SDK_PLUGINS,
|
|
7
8
|
buildSdkHomeDownloadUrl,
|
|
8
9
|
buildSdkHomeVersionUrl,
|
|
10
|
+
downloadIosSdkToBundled,
|
|
9
11
|
fetchSdkHomeIosDownloadUrl,
|
|
10
12
|
fetchSdkHomeIosVersion,
|
|
11
13
|
fetchSdkHomeVersions,
|
|
12
14
|
resolveIosSdkRootFromDirectory,
|
|
13
15
|
resolveIosSdkZipFileName,
|
|
14
16
|
} from "../src/remote/sdkHomeDownload.js";
|
|
17
|
+
import { resolveIosSdkCacheLayout } from "../src/cache.js";
|
|
15
18
|
|
|
16
19
|
describe("sdk-home iOS SDK download client", () => {
|
|
17
20
|
afterEach(() => {
|
|
@@ -121,4 +124,101 @@ describe("sdk-home iOS SDK download client", () => {
|
|
|
121
124
|
fs.rmSync(root, { recursive: true, force: true });
|
|
122
125
|
}
|
|
123
126
|
});
|
|
127
|
+
|
|
128
|
+
it("reuses an existing iOS SDK cache for the latest server version", async () => {
|
|
129
|
+
const version = "99.88.77-cache-test";
|
|
130
|
+
const cacheRoot = fs.mkdtempSync(path.join(os.tmpdir(), "meet-sdk-tool-cache-"));
|
|
131
|
+
const cacheLayout = resolveIosSdkCacheLayout({
|
|
132
|
+
version,
|
|
133
|
+
packageType: "native",
|
|
134
|
+
plugins: [...DEFAULT_IOS_SDK_PLUGINS],
|
|
135
|
+
cacheRoot,
|
|
136
|
+
});
|
|
137
|
+
fs.mkdirSync(path.join(cacheLayout.extractDir, "sdk"), { recursive: true });
|
|
138
|
+
fs.mkdirSync(path.join(cacheLayout.extractDir, "plugins"), { recursive: true });
|
|
139
|
+
const fetchMock = vi.fn(async (input: string | URL) => {
|
|
140
|
+
const url = String(input);
|
|
141
|
+
if (url.includes("/sdk/home/sdk-download/getDownLoadUrl")) {
|
|
142
|
+
throw new Error("download URL should not be requested when cache is current");
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
ok: true,
|
|
146
|
+
status: 200,
|
|
147
|
+
text: async () =>
|
|
148
|
+
JSON.stringify({
|
|
149
|
+
code: 200,
|
|
150
|
+
data: {
|
|
151
|
+
result: {
|
|
152
|
+
android: { ver: "1.0.0", date: "2026-01-01" },
|
|
153
|
+
ios: { ver: version, date: "2026-06-26" },
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
}),
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch);
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
const result = await downloadIosSdkToBundled(path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."), {
|
|
163
|
+
baseUrl: "https://example.com",
|
|
164
|
+
cacheRoot,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
expect(result.version).toBe(version);
|
|
168
|
+
expect(result.downloaded).toBe(false);
|
|
169
|
+
expect(result.resolvedSdkRoot).toBe(cacheLayout.extractDir);
|
|
170
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
171
|
+
} finally {
|
|
172
|
+
fs.rmSync(cacheRoot, { recursive: true, force: true });
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("reuses a higher local iOS SDK cache instead of downloading an older server version", async () => {
|
|
177
|
+
const serverVersion = "99.88.77-cache-test";
|
|
178
|
+
const cachedVersion = "99.88.78-cache-test";
|
|
179
|
+
const cacheRoot = fs.mkdtempSync(path.join(os.tmpdir(), "meet-sdk-tool-cache-"));
|
|
180
|
+
const cacheLayout = resolveIosSdkCacheLayout({
|
|
181
|
+
version: cachedVersion,
|
|
182
|
+
packageType: "native",
|
|
183
|
+
plugins: [...DEFAULT_IOS_SDK_PLUGINS],
|
|
184
|
+
cacheRoot,
|
|
185
|
+
});
|
|
186
|
+
fs.mkdirSync(path.join(cacheLayout.extractDir, "sdk"), { recursive: true });
|
|
187
|
+
fs.mkdirSync(path.join(cacheLayout.extractDir, "plugins"), { recursive: true });
|
|
188
|
+
const fetchMock = vi.fn(async (input: string | URL) => {
|
|
189
|
+
const url = String(input);
|
|
190
|
+
if (url.includes("/sdk/home/sdk-download/getDownLoadUrl")) {
|
|
191
|
+
throw new Error("download URL should not be requested when a higher cache is available");
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
ok: true,
|
|
195
|
+
status: 200,
|
|
196
|
+
text: async () =>
|
|
197
|
+
JSON.stringify({
|
|
198
|
+
code: 200,
|
|
199
|
+
data: {
|
|
200
|
+
result: {
|
|
201
|
+
android: { ver: "1.0.0", date: "2026-01-01" },
|
|
202
|
+
ios: { ver: serverVersion, date: "2026-06-26" },
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
}),
|
|
206
|
+
};
|
|
207
|
+
});
|
|
208
|
+
vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch);
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
const result = await downloadIosSdkToBundled(path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."), {
|
|
212
|
+
baseUrl: "https://example.com",
|
|
213
|
+
cacheRoot,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
expect(result.version).toBe(cachedVersion);
|
|
217
|
+
expect(result.downloaded).toBe(false);
|
|
218
|
+
expect(result.resolvedSdkRoot).toBe(cacheLayout.extractDir);
|
|
219
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
220
|
+
} finally {
|
|
221
|
+
fs.rmSync(cacheRoot, { recursive: true, force: true });
|
|
222
|
+
}
|
|
223
|
+
});
|
|
124
224
|
});
|