@leonxin/meetgames 0.1.16 → 0.1.18
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 +32 -39
- package/dist/cli.js.map +1 -1
- package/dist/core/doctor.js +1 -1
- package/dist/core/doctor.js.map +1 -1
- package/dist/ios/integrate.d.ts.map +1 -1
- package/dist/ios/integrate.js +11 -10
- package/dist/ios/integrate.js.map +1 -1
- package/dist/ios/pbxprojEditor.d.ts.map +1 -1
- package/dist/ios/pbxprojEditor.js +5 -8
- package/dist/ios/pbxprojEditor.js.map +1 -1
- package/dist/mcp/service.d.ts.map +1 -1
- package/dist/mcp/service.js +3 -1
- package/dist/mcp/service.js.map +1 -1
- package/dist/remote/sdkHomeDownload.d.ts +6 -3
- package/dist/remote/sdkHomeDownload.d.ts.map +1 -1
- package/dist/remote/sdkHomeDownload.js +139 -26
- package/dist/remote/sdkHomeDownload.js.map +1 -1
- package/docs/API.md +1 -1
- package/docs/CLI.md +4 -6
- package/package.json +1 -1
- package/src/cache.ts +2 -1
- package/src/cli.ts +29 -39
- package/src/core/doctor.ts +1 -1
- package/src/ios/integrate.ts +12 -11
- package/src/ios/pbxprojEditor.ts +6 -8
- package/src/mcp/service.ts +7 -1
- package/src/remote/sdkHomeDownload.ts +144 -29
- package/tests/pipeline.ios.test.ts +2 -1
- package/tests/sdkHomeDownload.test.ts +151 -0
|
@@ -2,12 +2,33 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { syncMeetSdkIosVersionToConfig } from "../config/meetSdkIosConfig.js";
|
|
5
|
+
import { hasSdkModuleKey, type MeetSdkRemoteConfig } from "../config/meetSdkRemoteConfig.js";
|
|
5
6
|
import { resolveIosSdkCacheLayout, withCacheLock, writeIosSdkCacheMetadata } from "../cache.js";
|
|
6
7
|
|
|
7
8
|
export const defaultSdkHomeApiBaseUrl = "https://business-api.meetgames.com";
|
|
8
9
|
export const DEFAULT_IOS_SDK_PLUGINS = ["guest", "facebook", "google", "apple", "apple_pay", "dataAppsFlyer"] as const;
|
|
9
10
|
export const DEFAULT_IOS_SDK_PACKAGE_TYPE = "native";
|
|
10
11
|
|
|
12
|
+
const IOS_SDK_DOWNLOAD_PLUGIN_BY_SUBKEY: Record<string, string> = {
|
|
13
|
+
guest: "guest",
|
|
14
|
+
email: "email",
|
|
15
|
+
facebook: "facebook",
|
|
16
|
+
google: "google",
|
|
17
|
+
snapchat: "snapchat",
|
|
18
|
+
discord: "discord",
|
|
19
|
+
line: "line",
|
|
20
|
+
naver: "naver",
|
|
21
|
+
kakao: "kakao",
|
|
22
|
+
tiktok: "tiktok",
|
|
23
|
+
apple: "apple",
|
|
24
|
+
googleIap: "google_pay",
|
|
25
|
+
appleIap: "apple_pay",
|
|
26
|
+
appsflyer: "dataAppsFlyer",
|
|
27
|
+
firebase: "dataFirebase",
|
|
28
|
+
adjust: "dataAdjust",
|
|
29
|
+
facebookdata: "dataFacebook",
|
|
30
|
+
};
|
|
31
|
+
|
|
11
32
|
const SDK_HOME_VERSION_PATH = "sdk/home/version";
|
|
12
33
|
const SDK_HOME_DOWNLOAD_URL_PATH = "sdk/home/sdk-download/getDownLoadUrl";
|
|
13
34
|
|
|
@@ -33,9 +54,9 @@ export interface SdkHomeDownloadUrlRequest {
|
|
|
33
54
|
|
|
34
55
|
export interface DownloadIosSdkOptions {
|
|
35
56
|
baseUrl?: string;
|
|
36
|
-
version?: string;
|
|
37
57
|
plugins?: readonly string[] | string;
|
|
38
58
|
packageType?: string;
|
|
59
|
+
cacheRoot?: string;
|
|
39
60
|
signal?: AbortSignal;
|
|
40
61
|
}
|
|
41
62
|
|
|
@@ -43,13 +64,14 @@ export interface DownloadIosSdkResult {
|
|
|
43
64
|
version: string;
|
|
44
65
|
versionDate: string;
|
|
45
66
|
versionUrl: string;
|
|
46
|
-
downloadApiUrl
|
|
47
|
-
sdkZipUrl
|
|
67
|
+
downloadApiUrl?: string;
|
|
68
|
+
sdkZipUrl?: string;
|
|
48
69
|
zipPath: string;
|
|
49
70
|
extractDir: string;
|
|
50
71
|
resolvedSdkRoot: string;
|
|
51
72
|
iosConfigPath: string;
|
|
52
73
|
cacheMetadataPath: string;
|
|
74
|
+
downloaded: boolean;
|
|
53
75
|
}
|
|
54
76
|
|
|
55
77
|
function isRecord(value: unknown): value is JsonRecord {
|
|
@@ -73,6 +95,20 @@ function pluginsToList(plugins: readonly string[] | string | undefined): string[
|
|
|
73
95
|
.filter(Boolean);
|
|
74
96
|
}
|
|
75
97
|
|
|
98
|
+
export function resolveIosSdkDownloadPluginsFromRemoteConfig(config: MeetSdkRemoteConfig): string[] {
|
|
99
|
+
const plugins: string[] = [];
|
|
100
|
+
for (const bucket of Object.values(config.sdkModules)) {
|
|
101
|
+
if (!bucket || typeof bucket !== "object") continue;
|
|
102
|
+
const scopeRecord = bucket as Record<string, unknown>;
|
|
103
|
+
for (const subKey of Object.keys(scopeRecord)) {
|
|
104
|
+
if (!hasSdkModuleKey(scopeRecord, subKey)) continue;
|
|
105
|
+
const plugin = IOS_SDK_DOWNLOAD_PLUGIN_BY_SUBKEY[subKey];
|
|
106
|
+
if (plugin) plugins.push(plugin);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return [...new Set(plugins)];
|
|
110
|
+
}
|
|
111
|
+
|
|
76
112
|
export function buildSdkHomeVersionUrl(baseUrl: string): string {
|
|
77
113
|
return joinBaseAndPath(baseUrl, SDK_HOME_VERSION_PATH).toString();
|
|
78
114
|
}
|
|
@@ -188,6 +224,68 @@ export function resolveIosSdkRootFromDirectory(bundledDir: string): string {
|
|
|
188
224
|
throw new Error(`iOS SDK layout invalid under ${bundledDir}: need sdk/ + plugins/ at top level or under one version directory.`);
|
|
189
225
|
}
|
|
190
226
|
|
|
227
|
+
function tryResolveIosSdkRootFromDirectory(bundledDir: string): string | null {
|
|
228
|
+
try {
|
|
229
|
+
return resolveIosSdkRootFromDirectory(bundledDir);
|
|
230
|
+
} catch {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function compareSdkVersions(a: string, b: string): number {
|
|
236
|
+
const left = a.split(/[.-]/);
|
|
237
|
+
const right = b.split(/[.-]/);
|
|
238
|
+
const len = Math.max(left.length, right.length);
|
|
239
|
+
for (let i = 0; i < len; i += 1) {
|
|
240
|
+
const l = left[i] ?? "0";
|
|
241
|
+
const r = right[i] ?? "0";
|
|
242
|
+
const ln = /^\d+$/.test(l) ? Number(l) : null;
|
|
243
|
+
const rn = /^\d+$/.test(r) ? Number(r) : null;
|
|
244
|
+
if (ln !== null && rn !== null) {
|
|
245
|
+
if (ln !== rn) return ln - rn;
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
const cmp = l.localeCompare(r);
|
|
249
|
+
if (cmp !== 0) return cmp;
|
|
250
|
+
}
|
|
251
|
+
return 0;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function findReusableCachedIosSdk(params: {
|
|
255
|
+
cacheRoot?: string;
|
|
256
|
+
packageType: string;
|
|
257
|
+
plugins: readonly string[];
|
|
258
|
+
serverVersion: string;
|
|
259
|
+
}): { version: string; layout: ReturnType<typeof resolveIosSdkCacheLayout>; resolvedSdkRoot: string } | null {
|
|
260
|
+
const probe = resolveIosSdkCacheLayout({
|
|
261
|
+
version: "__probe__",
|
|
262
|
+
packageType: params.packageType,
|
|
263
|
+
plugins: params.plugins,
|
|
264
|
+
cacheRoot: params.cacheRoot,
|
|
265
|
+
});
|
|
266
|
+
const packageDir = path.dirname(path.dirname(probe.baseDir));
|
|
267
|
+
if (!fs.existsSync(packageDir)) return null;
|
|
268
|
+
|
|
269
|
+
let best: { version: string; layout: ReturnType<typeof resolveIosSdkCacheLayout>; resolvedSdkRoot: string } | null = null;
|
|
270
|
+
for (const ent of fs.readdirSync(packageDir, { withFileTypes: true })) {
|
|
271
|
+
if (!ent.isDirectory() || ent.name.startsWith(".")) continue;
|
|
272
|
+
const comparedToServer = compareSdkVersions(ent.name, params.serverVersion);
|
|
273
|
+
if (comparedToServer < 0) continue;
|
|
274
|
+
const layout = resolveIosSdkCacheLayout({
|
|
275
|
+
version: ent.name,
|
|
276
|
+
packageType: params.packageType,
|
|
277
|
+
plugins: params.plugins,
|
|
278
|
+
cacheRoot: params.cacheRoot,
|
|
279
|
+
});
|
|
280
|
+
const resolvedSdkRoot = tryResolveIosSdkRootFromDirectory(layout.extractDir);
|
|
281
|
+
if (!resolvedSdkRoot) continue;
|
|
282
|
+
if (!best || compareSdkVersions(ent.name, best.version) > 0) {
|
|
283
|
+
best = { version: ent.name, layout, resolvedSdkRoot };
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return best;
|
|
287
|
+
}
|
|
288
|
+
|
|
191
289
|
export async function downloadBinaryFile(url: string, absPath: string, signal?: AbortSignal): Promise<void> {
|
|
192
290
|
let res: Response;
|
|
193
291
|
try {
|
|
@@ -236,25 +334,39 @@ export async function downloadIosSdkToBundled(
|
|
|
236
334
|
const baseUrl = options.baseUrl || defaultSdkHomeApiBaseUrl;
|
|
237
335
|
const packageType = options.packageType || DEFAULT_IOS_SDK_PACKAGE_TYPE;
|
|
238
336
|
const plugins = pluginsToList(options.plugins);
|
|
239
|
-
const versionResult = options.
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const downloadResult = await fetchSdkHomeIosDownloadUrl({
|
|
244
|
-
baseUrl,
|
|
245
|
-
version,
|
|
246
|
-
plugins,
|
|
337
|
+
const versionResult = await fetchSdkHomeIosVersion({ baseUrl, signal: options.signal });
|
|
338
|
+
const serverVersion = versionResult.ios.ver;
|
|
339
|
+
const reusableCache = findReusableCachedIosSdk({
|
|
340
|
+
cacheRoot: options.cacheRoot,
|
|
247
341
|
packageType,
|
|
248
|
-
|
|
342
|
+
plugins,
|
|
343
|
+
serverVersion,
|
|
249
344
|
});
|
|
250
|
-
const
|
|
345
|
+
const version = reusableCache?.version ?? serverVersion;
|
|
346
|
+
const cacheLayout =
|
|
347
|
+
reusableCache?.layout ?? resolveIosSdkCacheLayout({ version, packageType, plugins, cacheRoot: options.cacheRoot });
|
|
251
348
|
const extractDir = cacheLayout.extractDir;
|
|
252
349
|
const zipPath = cacheLayout.zipPath;
|
|
350
|
+
let downloadApiUrl: string | undefined;
|
|
351
|
+
let sdkZipUrl: string | undefined;
|
|
352
|
+
let downloaded = false;
|
|
253
353
|
|
|
254
354
|
const downloadAndExtract = async (): Promise<void> => {
|
|
255
|
-
|
|
355
|
+
const cachedRoot = tryResolveIosSdkRootFromDirectory(extractDir);
|
|
356
|
+
if (cachedRoot) return;
|
|
357
|
+
const fetchedDownload = await fetchSdkHomeIosDownloadUrl({
|
|
358
|
+
baseUrl,
|
|
359
|
+
version,
|
|
360
|
+
plugins,
|
|
361
|
+
packageType,
|
|
362
|
+
signal: options.signal,
|
|
363
|
+
});
|
|
364
|
+
downloadApiUrl = fetchedDownload.url;
|
|
365
|
+
sdkZipUrl = fetchedDownload.sdkZipUrl;
|
|
366
|
+
await downloadBinaryFile(fetchedDownload.sdkZipUrl, zipPath, options.signal);
|
|
256
367
|
fs.rmSync(extractDir, { recursive: true, force: true });
|
|
257
368
|
await extractZip(zipPath, extractDir);
|
|
369
|
+
downloaded = true;
|
|
258
370
|
};
|
|
259
371
|
await withCacheLock(cacheLayout.lockDir, downloadAndExtract);
|
|
260
372
|
const iosConfigPath = syncMeetSdkIosVersionToConfig({
|
|
@@ -266,30 +378,33 @@ export async function downloadIosSdkToBundled(
|
|
|
266
378
|
});
|
|
267
379
|
const resolvedSdkRoot = resolveIosSdkRootFromDirectory(extractDir);
|
|
268
380
|
const cacheMetadataPath = cacheLayout.metadataPath;
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
381
|
+
if (downloaded && downloadApiUrl && sdkZipUrl) {
|
|
382
|
+
writeIosSdkCacheMetadata({
|
|
383
|
+
metadataPath: cacheMetadataPath,
|
|
384
|
+
version,
|
|
385
|
+
date: versionResult.ios.date,
|
|
386
|
+
packageType,
|
|
387
|
+
plugins,
|
|
388
|
+
versionUrl: versionResult.url,
|
|
389
|
+
downloadApiUrl,
|
|
390
|
+
sdkZipUrl,
|
|
391
|
+
zipPath,
|
|
392
|
+
extractDir,
|
|
393
|
+
resolvedSdkRoot,
|
|
394
|
+
});
|
|
395
|
+
}
|
|
282
396
|
|
|
283
397
|
return {
|
|
284
398
|
version,
|
|
285
399
|
versionDate: versionResult.ios.date,
|
|
286
400
|
versionUrl: versionResult.url,
|
|
287
|
-
downloadApiUrl
|
|
288
|
-
sdkZipUrl
|
|
401
|
+
downloadApiUrl,
|
|
402
|
+
sdkZipUrl,
|
|
289
403
|
zipPath,
|
|
290
404
|
extractDir,
|
|
291
405
|
resolvedSdkRoot,
|
|
292
406
|
iosConfigPath,
|
|
293
407
|
cacheMetadataPath,
|
|
408
|
+
downloaded,
|
|
294
409
|
};
|
|
295
410
|
}
|
|
@@ -423,7 +423,8 @@ describe.skipIf(!hasIosProjectFixture)("pipeline ios fixture", () => {
|
|
|
423
423
|
const { report, patch, binaryCopies } = await runPipeline(ctx, manifest(), { dryRun: true });
|
|
424
424
|
|
|
425
425
|
expect(report.errors).toEqual([]);
|
|
426
|
-
expect(report.warnings.join("\n")).toContain("
|
|
426
|
+
expect(report.warnings.join("\n")).not.toContain("GoogleService-Info.plist");
|
|
427
|
+
expect((report.logs ?? []).join("\n")).toContain("would download GoogleService-Info.plist to native-sample/GoogleService-Info.plist");
|
|
427
428
|
expect(plannedIosAsset(patch, binaryCopies, "TOPDataFirebasePlugin.framework")).toBe(true);
|
|
428
429
|
} finally {
|
|
429
430
|
fs.rmSync(tmp, { recursive: true, force: true });
|
|
@@ -2,16 +2,20 @@ 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,
|
|
14
|
+
resolveIosSdkDownloadPluginsFromRemoteConfig,
|
|
12
15
|
resolveIosSdkRootFromDirectory,
|
|
13
16
|
resolveIosSdkZipFileName,
|
|
14
17
|
} from "../src/remote/sdkHomeDownload.js";
|
|
18
|
+
import { resolveIosSdkCacheLayout } from "../src/cache.js";
|
|
15
19
|
|
|
16
20
|
describe("sdk-home iOS SDK download client", () => {
|
|
17
21
|
afterEach(() => {
|
|
@@ -104,6 +108,56 @@ describe("sdk-home iOS SDK download client", () => {
|
|
|
104
108
|
expect(resolveIosSdkZipFileName("1.6.0.5")).toBe("topSDK-ios--V1.6.0.5.zip");
|
|
105
109
|
});
|
|
106
110
|
|
|
111
|
+
it("resolves SDK download plugins from the iOS remote config", () => {
|
|
112
|
+
expect(
|
|
113
|
+
resolveIosSdkDownloadPluginsFromRemoteConfig({
|
|
114
|
+
packageName: "com.example.app",
|
|
115
|
+
channel: "APPLE",
|
|
116
|
+
devicePlatform: "ios",
|
|
117
|
+
topsdk: { appId: "app", appSecret: "secret" },
|
|
118
|
+
sdkModules: {
|
|
119
|
+
login: {
|
|
120
|
+
guest: {},
|
|
121
|
+
email: {},
|
|
122
|
+
facebook: { clientId: "fb", scheme: "fb", secret: "token" },
|
|
123
|
+
google: { clientId: "google", scheme: "google" },
|
|
124
|
+
snapchat: { clientId: "snap", redirect: "snap://callback" },
|
|
125
|
+
line: { clientId: "line", scheme: "line" },
|
|
126
|
+
naver: { clientId: "naver", secret: "secret", scheme: "naver" },
|
|
127
|
+
kakao: { clientId: "kakao", scheme: "kakao" },
|
|
128
|
+
tiktok: { clientId: "tiktok", secret: "secret", redirect: "tiktok://callback" },
|
|
129
|
+
discord: { clientId: "discord", secret: "secret", redirect: "https://example.invalid/discord" },
|
|
130
|
+
apple: {},
|
|
131
|
+
},
|
|
132
|
+
payment: { appleIap: {} },
|
|
133
|
+
analytics: {
|
|
134
|
+
appsflyer: { devKey: "af", appleAppId: "123" },
|
|
135
|
+
firebase: { firebase_file_url: "https://cdn.example.invalid/GoogleService-Info.plist" },
|
|
136
|
+
adjust: { appCode: "adjust" },
|
|
137
|
+
facebookdata: { clientId: "fb", scheme: "fb", secret: "token" },
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
})
|
|
141
|
+
).toEqual([
|
|
142
|
+
"guest",
|
|
143
|
+
"email",
|
|
144
|
+
"facebook",
|
|
145
|
+
"google",
|
|
146
|
+
"snapchat",
|
|
147
|
+
"line",
|
|
148
|
+
"naver",
|
|
149
|
+
"kakao",
|
|
150
|
+
"tiktok",
|
|
151
|
+
"discord",
|
|
152
|
+
"apple",
|
|
153
|
+
"apple_pay",
|
|
154
|
+
"dataAppsFlyer",
|
|
155
|
+
"dataFirebase",
|
|
156
|
+
"dataAdjust",
|
|
157
|
+
"dataFacebook",
|
|
158
|
+
]);
|
|
159
|
+
});
|
|
160
|
+
|
|
107
161
|
it("resolves top-level and nested extracted SDK layouts", () => {
|
|
108
162
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "meet-sdk-tool-ios-"));
|
|
109
163
|
try {
|
|
@@ -121,4 +175,101 @@ describe("sdk-home iOS SDK download client", () => {
|
|
|
121
175
|
fs.rmSync(root, { recursive: true, force: true });
|
|
122
176
|
}
|
|
123
177
|
});
|
|
178
|
+
|
|
179
|
+
it("reuses an existing iOS SDK cache for the latest server version", async () => {
|
|
180
|
+
const version = "99.88.77-cache-test";
|
|
181
|
+
const cacheRoot = fs.mkdtempSync(path.join(os.tmpdir(), "meet-sdk-tool-cache-"));
|
|
182
|
+
const cacheLayout = resolveIosSdkCacheLayout({
|
|
183
|
+
version,
|
|
184
|
+
packageType: "native",
|
|
185
|
+
plugins: [...DEFAULT_IOS_SDK_PLUGINS],
|
|
186
|
+
cacheRoot,
|
|
187
|
+
});
|
|
188
|
+
fs.mkdirSync(path.join(cacheLayout.extractDir, "sdk"), { recursive: true });
|
|
189
|
+
fs.mkdirSync(path.join(cacheLayout.extractDir, "plugins"), { recursive: true });
|
|
190
|
+
const fetchMock = vi.fn(async (input: string | URL) => {
|
|
191
|
+
const url = String(input);
|
|
192
|
+
if (url.includes("/sdk/home/sdk-download/getDownLoadUrl")) {
|
|
193
|
+
throw new Error("download URL should not be requested when cache is current");
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
ok: true,
|
|
197
|
+
status: 200,
|
|
198
|
+
text: async () =>
|
|
199
|
+
JSON.stringify({
|
|
200
|
+
code: 200,
|
|
201
|
+
data: {
|
|
202
|
+
result: {
|
|
203
|
+
android: { ver: "1.0.0", date: "2026-01-01" },
|
|
204
|
+
ios: { ver: version, date: "2026-06-26" },
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
}),
|
|
208
|
+
};
|
|
209
|
+
});
|
|
210
|
+
vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch);
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
const result = await downloadIosSdkToBundled(path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."), {
|
|
214
|
+
baseUrl: "https://example.com",
|
|
215
|
+
cacheRoot,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
expect(result.version).toBe(version);
|
|
219
|
+
expect(result.downloaded).toBe(false);
|
|
220
|
+
expect(result.resolvedSdkRoot).toBe(cacheLayout.extractDir);
|
|
221
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
222
|
+
} finally {
|
|
223
|
+
fs.rmSync(cacheRoot, { recursive: true, force: true });
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("reuses a higher local iOS SDK cache instead of downloading an older server version", async () => {
|
|
228
|
+
const serverVersion = "99.88.77-cache-test";
|
|
229
|
+
const cachedVersion = "99.88.78-cache-test";
|
|
230
|
+
const cacheRoot = fs.mkdtempSync(path.join(os.tmpdir(), "meet-sdk-tool-cache-"));
|
|
231
|
+
const cacheLayout = resolveIosSdkCacheLayout({
|
|
232
|
+
version: cachedVersion,
|
|
233
|
+
packageType: "native",
|
|
234
|
+
plugins: [...DEFAULT_IOS_SDK_PLUGINS],
|
|
235
|
+
cacheRoot,
|
|
236
|
+
});
|
|
237
|
+
fs.mkdirSync(path.join(cacheLayout.extractDir, "sdk"), { recursive: true });
|
|
238
|
+
fs.mkdirSync(path.join(cacheLayout.extractDir, "plugins"), { recursive: true });
|
|
239
|
+
const fetchMock = vi.fn(async (input: string | URL) => {
|
|
240
|
+
const url = String(input);
|
|
241
|
+
if (url.includes("/sdk/home/sdk-download/getDownLoadUrl")) {
|
|
242
|
+
throw new Error("download URL should not be requested when a higher cache is available");
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
ok: true,
|
|
246
|
+
status: 200,
|
|
247
|
+
text: async () =>
|
|
248
|
+
JSON.stringify({
|
|
249
|
+
code: 200,
|
|
250
|
+
data: {
|
|
251
|
+
result: {
|
|
252
|
+
android: { ver: "1.0.0", date: "2026-01-01" },
|
|
253
|
+
ios: { ver: serverVersion, date: "2026-06-26" },
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
}),
|
|
257
|
+
};
|
|
258
|
+
});
|
|
259
|
+
vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch);
|
|
260
|
+
|
|
261
|
+
try {
|
|
262
|
+
const result = await downloadIosSdkToBundled(path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."), {
|
|
263
|
+
baseUrl: "https://example.com",
|
|
264
|
+
cacheRoot,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
expect(result.version).toBe(cachedVersion);
|
|
268
|
+
expect(result.downloaded).toBe(false);
|
|
269
|
+
expect(result.resolvedSdkRoot).toBe(cacheLayout.extractDir);
|
|
270
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
271
|
+
} finally {
|
|
272
|
+
fs.rmSync(cacheRoot, { recursive: true, force: true });
|
|
273
|
+
}
|
|
274
|
+
});
|
|
124
275
|
});
|