@leonxin/meetgames 0.1.18 → 0.1.19
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/README.md +5 -4
- package/dist/cache.d.ts +16 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +21 -0
- package/dist/cache.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +20 -16
- package/dist/cli.js.map +1 -1
- package/dist/config/meetSdkDefaultConfig.d.ts +7 -11
- package/dist/config/meetSdkDefaultConfig.d.ts.map +1 -1
- package/dist/config/meetSdkDefaultConfig.js +216 -53
- package/dist/config/meetSdkDefaultConfig.js.map +1 -1
- package/dist/config/meetSdkIosConfig.d.ts +4 -5
- package/dist/config/meetSdkIosConfig.d.ts.map +1 -1
- package/dist/config/meetSdkIosConfig.js +19 -19
- package/dist/config/meetSdkIosConfig.js.map +1 -1
- package/dist/contracts/types.d.ts +4 -0
- package/dist/contracts/types.d.ts.map +1 -1
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +2 -0
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/previewPatches.d.ts +2 -2
- package/dist/core/previewPatches.d.ts.map +1 -1
- package/dist/core/previewPatches.js +3 -3
- package/dist/core/previewPatches.js.map +1 -1
- package/dist/core/workspace.d.ts.map +1 -1
- package/dist/core/workspace.js +1 -0
- package/dist/core/workspace.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/mcp/service.d.ts +2 -0
- package/dist/mcp/service.d.ts.map +1 -1
- package/dist/mcp/service.js +8 -7
- package/dist/mcp/service.js.map +1 -1
- package/dist/ops/handlers.d.ts.map +1 -1
- package/dist/ops/handlers.js +4 -0
- package/dist/ops/handlers.js.map +1 -1
- package/dist/remote/sdkHomeDownload.d.ts +4 -5
- package/dist/remote/sdkHomeDownload.d.ts.map +1 -1
- package/dist/remote/sdkHomeDownload.js +38 -12
- package/dist/remote/sdkHomeDownload.js.map +1 -1
- package/docs/API.md +13 -13
- package/docs/CLI.md +27 -13
- package/docs/INTEGRATION.md +7 -6
- package/package.json +1 -1
- package/src/cache.ts +37 -0
- package/src/cli.ts +21 -14
- package/src/config/meetSdkDefaultConfig.ts +243 -59
- package/src/config/meetSdkIosConfig.ts +17 -21
- package/src/contracts/types.ts +4 -0
- package/src/core/doctor.ts +2 -0
- package/src/core/previewPatches.ts +3 -3
- package/src/core/workspace.ts +1 -0
- package/src/index.ts +5 -3
- package/src/mcp/service.ts +11 -7
- package/src/ops/handlers.ts +4 -0
- package/src/remote/sdkHomeDownload.ts +48 -16
- package/config/meetsdk-android.json +0 -171
- package/config/meetsdk-ios.json +0 -15
- package/tests/assemble.test.ts +0 -12
- package/tests/doctor.test.ts +0 -131
- package/tests/downloadGoogleServicesJson.test.ts +0 -47
- package/tests/fetch-remote.test.ts +0 -23
- package/tests/fetchConfigOverrides.test.ts +0 -28
- package/tests/fetchConfigWrite.test.ts +0 -54
- package/tests/fixtures-hosts.test.ts +0 -78
- package/tests/gradle.test.ts +0 -33
- package/tests/integration-json.test.ts +0 -29
- package/tests/ios.codeUtils.test.ts +0 -23
- package/tests/ios.sdkBundle.test.ts +0 -21
- package/tests/loadManifest.test.ts +0 -15
- package/tests/manifest-xml.test.ts +0 -30
- package/tests/mcp.e2e.ts +0 -214
- package/tests/mcp.service.test.ts +0 -53
- package/tests/meetSdkRemoteConfig.test.ts +0 -482
- package/tests/meetSdkRemoteGradle.test.ts +0 -414
- package/tests/pipeline.android.test.ts +0 -149
- package/tests/pipeline.integration-json.test.ts +0 -58
- package/tests/pipeline.ios.test.ts +0 -609
- package/tests/pipeline.preview.patch.test.ts +0 -85
- package/tests/platformSelection.test.ts +0 -77
- package/tests/sdkHomeDownload.test.ts +0 -275
- package/tests/sdkVersionConfig.test.ts +0 -131
- package/tests/topsdk.test.ts +0 -53
- package/tests/topsdkDownloadSdkConfig.test.ts +0 -81
- package/tests/topsdkFeatureModules.test.ts +0 -116
|
@@ -1,42 +1,159 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import {
|
|
4
|
+
MEETSDK_ANDROID_CONFIG_FILENAME,
|
|
5
|
+
resolveAndroidSdkCacheLayout,
|
|
6
|
+
resolveMeetSdkAndroidConfigCachePath,
|
|
7
|
+
withCacheLock,
|
|
8
|
+
} from "../cache.js";
|
|
9
|
+
import {
|
|
10
|
+
buildSdkHomeDownloadUrl,
|
|
11
|
+
defaultSdkHomeApiBaseUrl,
|
|
12
|
+
downloadBinaryFile,
|
|
13
|
+
extractZip,
|
|
14
|
+
fetchSdkHomeVersions,
|
|
15
|
+
type SdkHomePlatformVersion,
|
|
16
|
+
} from "../remote/sdkHomeDownload.js";
|
|
17
|
+
import {
|
|
18
|
+
DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES,
|
|
19
|
+
tryParseAsMeetSdkDefaultConfig,
|
|
20
|
+
type MeetSdkDefaultConfig,
|
|
21
|
+
} from "./meetSdkRemoteConfig.js";
|
|
6
22
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const MEETSDK_CONFIG_DIR = "config";
|
|
23
|
+
const DEFAULT_GROUP_ID = "com.sino.topsdk";
|
|
24
|
+
const DEFAULT_ANDROID_SDK_PACKAGE_TYPE = "native";
|
|
10
25
|
|
|
11
|
-
|
|
12
|
-
new URL(`../../${MEETSDK_CONFIG_DIR}/${MEETSDK_ANDROID_DEFAULTS_FILENAME}`, import.meta.url)
|
|
13
|
-
);
|
|
26
|
+
type JsonRecord = Record<string, unknown>;
|
|
14
27
|
|
|
15
|
-
|
|
16
|
-
return
|
|
28
|
+
function isRecord(value: unknown): value is JsonRecord {
|
|
29
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17
30
|
}
|
|
18
31
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
function cloneDefaultConfig(value: MeetSdkDefaultConfig): MeetSdkDefaultConfig {
|
|
33
|
+
return JSON.parse(JSON.stringify(value)) as MeetSdkDefaultConfig;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function resolveSdkHomeApiBaseUrl(baseUrl?: string): string {
|
|
37
|
+
return baseUrl || process.env.MEETGAMES_SDK_HOME_API_BASE_URL?.trim() || defaultSdkHomeApiBaseUrl;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function parseJsonResponseEnvelope(body: unknown, label: string): unknown {
|
|
41
|
+
if (!isRecord(body)) throw new Error(`${label} response is not an object`);
|
|
42
|
+
const code = body.code;
|
|
43
|
+
if (code !== undefined && Number(code) !== 200) {
|
|
44
|
+
const message = typeof body.message === "string" ? body.message : JSON.stringify(body);
|
|
45
|
+
throw new Error(`${label} API error (code=${String(code)}): ${message}`);
|
|
25
46
|
}
|
|
26
|
-
|
|
27
|
-
|
|
47
|
+
return "data" in body ? body.data : body;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function fetchJson(url: string, signal?: AbortSignal): Promise<unknown> {
|
|
51
|
+
let res: Response;
|
|
52
|
+
try {
|
|
53
|
+
res = await fetch(url, { redirect: "follow", signal, headers: { Accept: "application/json" } });
|
|
54
|
+
} catch (e) {
|
|
55
|
+
const cause = e instanceof Error && "cause" in e && e.cause instanceof Error ? e.cause.message : null;
|
|
56
|
+
const detail = cause && cause !== (e instanceof Error ? e.message : String(e)) ? ` (${cause})` : "";
|
|
57
|
+
throw new Error(`GET ${url} failed: ${e instanceof Error ? e.message : String(e)}${detail}`);
|
|
58
|
+
}
|
|
59
|
+
if (!res.ok) {
|
|
60
|
+
const text = await res.text().catch(() => "");
|
|
61
|
+
const detail = text.trim() ? `: ${text.trim().slice(0, 1000)}` : "";
|
|
62
|
+
throw new Error(`GET ${url} failed: HTTP ${res.status}${detail}`);
|
|
63
|
+
}
|
|
64
|
+
const text = await res.text();
|
|
65
|
+
try {
|
|
66
|
+
return JSON.parse(text) as unknown;
|
|
67
|
+
} catch {
|
|
68
|
+
throw new Error(`GET ${url} did not return valid JSON`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function resolveMeetSdkAndroidConfigPath(cacheRoot?: string): string {
|
|
73
|
+
return resolveMeetSdkAndroidConfigCachePath(cacheRoot);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function readMeetSdkDefaultConfigFromPath(configPath: string): MeetSdkDefaultConfig {
|
|
77
|
+
const parsed = tryParseAsMeetSdkDefaultConfig(JSON.parse(fs.readFileSync(configPath, "utf8")) as unknown);
|
|
28
78
|
if (!parsed) {
|
|
29
|
-
throw new Error(
|
|
79
|
+
throw new Error(`${MEETSDK_ANDROID_CONFIG_FILENAME} is not a valid MeetSdk default config: ${configPath}`);
|
|
30
80
|
}
|
|
31
81
|
return parsed;
|
|
32
82
|
}
|
|
33
83
|
|
|
34
|
-
function
|
|
35
|
-
|
|
84
|
+
export function loadBuiltInMeetSdkDefaultConfig(options: { cacheRoot?: string; packageRoot?: string } = {}): MeetSdkDefaultConfig {
|
|
85
|
+
const cachePath = resolveMeetSdkAndroidConfigPath(options.cacheRoot);
|
|
86
|
+
if (fs.existsSync(cachePath)) return readMeetSdkDefaultConfigFromPath(cachePath);
|
|
87
|
+
return compatibilityDefaultConfig();
|
|
36
88
|
}
|
|
37
89
|
|
|
38
|
-
function
|
|
39
|
-
|
|
90
|
+
function compatibilityDefaultConfig(): MeetSdkDefaultConfig {
|
|
91
|
+
const raw = {
|
|
92
|
+
topsdk: {
|
|
93
|
+
version: "",
|
|
94
|
+
groupId: DEFAULT_GROUP_ID,
|
|
95
|
+
repositories: ["https://storage-sdk-gameplus.meetsocial.com/repository/TopSdk/"],
|
|
96
|
+
},
|
|
97
|
+
sdkModules: {
|
|
98
|
+
login: {
|
|
99
|
+
guest: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.login.guest] },
|
|
100
|
+
email: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.login.email] },
|
|
101
|
+
apple: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.login.apple] },
|
|
102
|
+
facebook: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.login.facebook] },
|
|
103
|
+
google: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.login.google] },
|
|
104
|
+
twitter: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.login.twitter] },
|
|
105
|
+
snapchat: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.login.snapchat] },
|
|
106
|
+
line: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.login.line] },
|
|
107
|
+
naver: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.login.naver] },
|
|
108
|
+
kakao: {
|
|
109
|
+
repositories: ["https://devrepo.kakao.com/nexus/content/groups/public/"],
|
|
110
|
+
dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.login.kakao],
|
|
111
|
+
},
|
|
112
|
+
tiktok: {
|
|
113
|
+
repositories: ["https://artifact.bytedance.com/repository/AwemeOpenSDK"],
|
|
114
|
+
dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.login.tiktok],
|
|
115
|
+
},
|
|
116
|
+
discord: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.login.discord] },
|
|
117
|
+
},
|
|
118
|
+
payment: {
|
|
119
|
+
googleIap: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.payment.googleIap] },
|
|
120
|
+
appleIap: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.payment.appleIap] },
|
|
121
|
+
onestoreIap: {
|
|
122
|
+
repositories: ["https://repo.onestore.co.kr/repository/onestore-sdk-public/"],
|
|
123
|
+
dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.payment.onestoreIap],
|
|
124
|
+
},
|
|
125
|
+
huaweiIap: {
|
|
126
|
+
repositories: ["https://developer.huawei.com/repo/"],
|
|
127
|
+
dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.payment.huaweiIap],
|
|
128
|
+
},
|
|
129
|
+
xiaomiIap: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.payment.xiaomiIap] },
|
|
130
|
+
},
|
|
131
|
+
analytics: {
|
|
132
|
+
appsflyer: {
|
|
133
|
+
repositories: ["mavenCentral"],
|
|
134
|
+
dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.analytics.appsflyer],
|
|
135
|
+
},
|
|
136
|
+
facebookdata: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.analytics.facebookdata] },
|
|
137
|
+
firebase: {
|
|
138
|
+
repositories: ["google"],
|
|
139
|
+
classpath: "com.google.gms:google-services:4.4.4",
|
|
140
|
+
applyplugin: "com.google.gms.google-services",
|
|
141
|
+
dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.analytics.firebase],
|
|
142
|
+
},
|
|
143
|
+
adjust: { dependencies: [...DEFAULT_TOPSDK_PLUGIN_DEPENDENCIES.analytics.adjust] },
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
const parsed = tryParseAsMeetSdkDefaultConfig(raw);
|
|
148
|
+
if (!parsed) throw new Error("embedded compatibility meetsdk-android defaults are invalid");
|
|
149
|
+
return parsed;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function writeMeetSdkAndroidConfigCache(config: MeetSdkDefaultConfig, cacheRoot?: string): string {
|
|
153
|
+
const configPath = resolveMeetSdkAndroidConfigPath(cacheRoot);
|
|
154
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
155
|
+
fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf8");
|
|
156
|
+
return configPath;
|
|
40
157
|
}
|
|
41
158
|
|
|
42
159
|
const latestAndroidVersionCache = new Map<string, Promise<SdkHomePlatformVersion>>();
|
|
@@ -51,50 +168,117 @@ async function fetchLatestAndroidSdkVersion(baseUrl?: string): Promise<SdkHomePl
|
|
|
51
168
|
return cached;
|
|
52
169
|
}
|
|
53
170
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
171
|
+
function androidChannelPlugin(channelType?: string): string {
|
|
172
|
+
const normalized = (channelType ?? "").trim().toUpperCase();
|
|
173
|
+
const map: Record<string, string> = {
|
|
174
|
+
GOOGLE: "google_channel",
|
|
175
|
+
ONESTORE: "onestore_channel",
|
|
176
|
+
XIAOMI: "xiaomi_channel",
|
|
177
|
+
HUAWEI: "huawei_channel",
|
|
178
|
+
};
|
|
179
|
+
return map[normalized] ?? "google_channel";
|
|
180
|
+
}
|
|
61
181
|
|
|
62
|
-
|
|
63
|
-
if (!fs.existsSync(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
182
|
+
function findMeetSdkAndroidConfigFile(root: string): string | null {
|
|
183
|
+
if (!fs.existsSync(root)) return null;
|
|
184
|
+
const stack = [root];
|
|
185
|
+
while (stack.length) {
|
|
186
|
+
const dir = stack.pop()!;
|
|
187
|
+
for (const ent of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
188
|
+
if (ent.name.startsWith("__MACOSX") || ent.name.startsWith("._")) continue;
|
|
189
|
+
const abs = path.join(dir, ent.name);
|
|
190
|
+
if (ent.isDirectory()) {
|
|
191
|
+
stack.push(abs);
|
|
192
|
+
} else if (ent.isFile() && ent.name === MEETSDK_ANDROID_CONFIG_FILENAME) {
|
|
193
|
+
return abs;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
69
196
|
}
|
|
70
|
-
|
|
71
|
-
if (typeof record.topsdk !== "object" || record.topsdk === null || Array.isArray(record.topsdk)) {
|
|
72
|
-
throw new Error(`built-in ${MEETSDK_ANDROID_DEFAULTS_FILENAME} does not contain topsdk object`);
|
|
73
|
-
}
|
|
74
|
-
const topsdk = record.topsdk as Record<string, unknown>;
|
|
75
|
-
topsdk.version = version;
|
|
76
|
-
if (params.date?.trim()) topsdk.date = params.date.trim();
|
|
77
|
-
fs.writeFileSync(configPath, `${JSON.stringify(record, null, 2)}\n`, "utf8");
|
|
78
|
-
return configPath;
|
|
197
|
+
return null;
|
|
79
198
|
}
|
|
80
199
|
|
|
200
|
+
function loadMeetSdkAndroidConfigFromExtracted(root: string, version: string, date?: string): MeetSdkDefaultConfig {
|
|
201
|
+
const configPath = findMeetSdkAndroidConfigFile(root);
|
|
202
|
+
if (!configPath) throw new Error(`${MEETSDK_ANDROID_CONFIG_FILENAME} not found under downloaded Android SDK: ${root}`);
|
|
203
|
+
const config = readMeetSdkDefaultConfigFromPath(configPath);
|
|
204
|
+
config.topsdk.version = config.topsdk.version || version;
|
|
205
|
+
config.topsdk.date = config.topsdk.date || date;
|
|
206
|
+
return config;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async function fetchSdkHomeAndroidConfig(params: {
|
|
210
|
+
baseUrl?: string;
|
|
211
|
+
version: string;
|
|
212
|
+
date?: string;
|
|
213
|
+
channelType?: string;
|
|
214
|
+
packageType?: string;
|
|
215
|
+
cacheRoot?: string;
|
|
216
|
+
signal?: AbortSignal;
|
|
217
|
+
}): Promise<{ url?: string; config: MeetSdkDefaultConfig }> {
|
|
218
|
+
const baseUrl = resolveSdkHomeApiBaseUrl(params.baseUrl);
|
|
219
|
+
const packageType = params.packageType || DEFAULT_ANDROID_SDK_PACKAGE_TYPE;
|
|
220
|
+
const plugins = [androidChannelPlugin(params.channelType)];
|
|
221
|
+
const layout = resolveAndroidSdkCacheLayout({
|
|
222
|
+
version: params.version,
|
|
223
|
+
packageType,
|
|
224
|
+
plugins,
|
|
225
|
+
cacheRoot: params.cacheRoot,
|
|
226
|
+
});
|
|
227
|
+
let downloadApiUrl: string | undefined;
|
|
228
|
+
const downloadAndExtract = async (): Promise<void> => {
|
|
229
|
+
if (findMeetSdkAndroidConfigFile(layout.extractDir)) return;
|
|
230
|
+
downloadApiUrl = buildSdkHomeDownloadUrl({
|
|
231
|
+
baseUrl,
|
|
232
|
+
version: params.version,
|
|
233
|
+
platform: "android",
|
|
234
|
+
packageType,
|
|
235
|
+
plugins,
|
|
236
|
+
});
|
|
237
|
+
const body = parseJsonResponseEnvelope(await fetchJson(downloadApiUrl, params.signal), "sdk-home Android download");
|
|
238
|
+
if (typeof body !== "string" || !body.trim()) {
|
|
239
|
+
throw new Error("sdk-home Android getDownLoadUrl response does not contain a download URL in data");
|
|
240
|
+
}
|
|
241
|
+
await downloadBinaryFile(body, layout.zipPath, params.signal);
|
|
242
|
+
fs.rmSync(layout.extractDir, { recursive: true, force: true });
|
|
243
|
+
await extractZip(layout.zipPath, layout.extractDir);
|
|
244
|
+
};
|
|
245
|
+
await withCacheLock(layout.lockDir, downloadAndExtract);
|
|
246
|
+
return {
|
|
247
|
+
url: downloadApiUrl,
|
|
248
|
+
config: loadMeetSdkAndroidConfigFromExtracted(layout.extractDir, params.version, params.date),
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const androidConfigCache = new Map<string, Promise<MeetSdkDefaultConfig>>();
|
|
253
|
+
|
|
81
254
|
/**
|
|
82
|
-
*
|
|
83
|
-
* The
|
|
84
|
-
* reflects the latest SDK version discovered from the download center.
|
|
255
|
+
* Android SDK defaults resolved from sdk-home and persisted under ~/.cache/meet-sdk-tool.
|
|
256
|
+
* The package config/ directory is no longer written at runtime.
|
|
85
257
|
*/
|
|
86
258
|
export async function loadMeetSdkDefaultConfigWithLatestAndroidVersion(options: {
|
|
87
259
|
sdkHomeApiBaseUrl?: string;
|
|
260
|
+
cacheRoot?: string;
|
|
88
261
|
packageRoot?: string;
|
|
262
|
+
channelType?: string;
|
|
263
|
+
packageType?: string;
|
|
89
264
|
} = {}): Promise<MeetSdkDefaultConfig> {
|
|
90
|
-
const defaults = cloneDefaultConfig(loadBuiltInMeetSdkDefaultConfig({ packageRoot: options.packageRoot }));
|
|
91
265
|
const latest = await fetchLatestAndroidSdkVersion(options.sdkHomeApiBaseUrl);
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
266
|
+
const baseUrl = resolveSdkHomeApiBaseUrl(options.sdkHomeApiBaseUrl);
|
|
267
|
+
const key = `${baseUrl}\n${latest.ver}\n${options.cacheRoot ?? ""}\n${options.channelType ?? ""}\n${options.packageType ?? ""}`;
|
|
268
|
+
let cached = androidConfigCache.get(key);
|
|
269
|
+
if (!cached) {
|
|
270
|
+
cached = fetchSdkHomeAndroidConfig({
|
|
271
|
+
baseUrl,
|
|
272
|
+
version: latest.ver,
|
|
273
|
+
date: latest.date,
|
|
274
|
+
channelType: options.channelType,
|
|
275
|
+
packageType: options.packageType,
|
|
276
|
+
cacheRoot: options.cacheRoot,
|
|
277
|
+
}).then(({ config }) => {
|
|
278
|
+
writeMeetSdkAndroidConfigCache(config, options.cacheRoot);
|
|
279
|
+
return cloneDefaultConfig(config);
|
|
280
|
+
});
|
|
281
|
+
androidConfigCache.set(key, cached);
|
|
282
|
+
}
|
|
283
|
+
return cloneDefaultConfig(await cached);
|
|
100
284
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
export const MEETSDK_IOS_CONFIG_FILENAME = "meetsdk-ios.json";
|
|
5
|
-
const MEETSDK_CONFIG_DIR = "config";
|
|
3
|
+
import { MEETSDK_IOS_CONFIG_FILENAME, resolveMeetSdkIosConfigCachePath } from "../cache.js";
|
|
6
4
|
|
|
7
5
|
export interface MeetSdkIosConfig {
|
|
8
6
|
topsdk: {
|
|
@@ -27,8 +25,8 @@ function normalizePlugins(value: unknown): string[] | undefined {
|
|
|
27
25
|
return plugins.length ? plugins : undefined;
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
export function resolveMeetSdkIosConfigPath(
|
|
31
|
-
return
|
|
28
|
+
export function resolveMeetSdkIosConfigPath(cacheRoot?: string): string {
|
|
29
|
+
return resolveMeetSdkIosConfigCachePath(cacheRoot);
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
export function tryParseAsMeetSdkIosConfig(raw: unknown): MeetSdkIosConfig | null {
|
|
@@ -44,8 +42,8 @@ export function tryParseAsMeetSdkIosConfig(raw: unknown): MeetSdkIosConfig | nul
|
|
|
44
42
|
};
|
|
45
43
|
}
|
|
46
44
|
|
|
47
|
-
export function loadMeetSdkIosConfig(
|
|
48
|
-
const configPath = resolveMeetSdkIosConfigPath(
|
|
45
|
+
export function loadMeetSdkIosConfig(cacheRoot?: string): MeetSdkIosConfig {
|
|
46
|
+
const configPath = resolveMeetSdkIosConfigPath(cacheRoot);
|
|
49
47
|
if (!fs.existsSync(configPath)) {
|
|
50
48
|
return { topsdk: { version: "" } };
|
|
51
49
|
}
|
|
@@ -56,15 +54,15 @@ export function loadMeetSdkIosConfig(packageRoot: string): MeetSdkIosConfig {
|
|
|
56
54
|
return parsed;
|
|
57
55
|
}
|
|
58
56
|
|
|
59
|
-
export function writeMeetSdkIosConfig(
|
|
60
|
-
const configPath = resolveMeetSdkIosConfigPath(
|
|
57
|
+
export function writeMeetSdkIosConfig(config: MeetSdkIosConfig, cacheRoot?: string): string {
|
|
58
|
+
const configPath = resolveMeetSdkIosConfigPath(cacheRoot);
|
|
61
59
|
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
62
60
|
fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf8");
|
|
63
61
|
return configPath;
|
|
64
62
|
}
|
|
65
63
|
|
|
66
64
|
export function syncMeetSdkIosVersionToConfig(params: {
|
|
67
|
-
|
|
65
|
+
cacheRoot?: string;
|
|
68
66
|
version: string;
|
|
69
67
|
date?: string;
|
|
70
68
|
packageType?: string;
|
|
@@ -73,17 +71,15 @@ export function syncMeetSdkIosVersionToConfig(params: {
|
|
|
73
71
|
const version = params.version.trim();
|
|
74
72
|
if (!version) throw new Error("iOS SDK version is empty");
|
|
75
73
|
|
|
76
|
-
const
|
|
77
|
-
const
|
|
74
|
+
const topsdk: MeetSdkIosConfig["topsdk"] = { version };
|
|
75
|
+
const date = params.date?.trim();
|
|
76
|
+
const packageType = params.packageType?.trim();
|
|
77
|
+
const plugins = params.plugins?.map((x) => x.trim()).filter(Boolean);
|
|
78
|
+
if (date) topsdk.date = date;
|
|
79
|
+
if (packageType) topsdk.packageType = packageType;
|
|
80
|
+
if (plugins?.length) topsdk.plugins = plugins;
|
|
78
81
|
const next: MeetSdkIosConfig = {
|
|
79
|
-
|
|
80
|
-
topsdk: {
|
|
81
|
-
...current.topsdk,
|
|
82
|
-
version,
|
|
83
|
-
date: nextDate,
|
|
84
|
-
packageType: params.packageType?.trim() || current.topsdk.packageType,
|
|
85
|
-
plugins: params.plugins?.map((x) => x.trim()).filter(Boolean) || current.topsdk.plugins,
|
|
86
|
-
},
|
|
82
|
+
topsdk,
|
|
87
83
|
};
|
|
88
|
-
return writeMeetSdkIosConfig(params.
|
|
84
|
+
return writeMeetSdkIosConfig(next, params.cacheRoot);
|
|
89
85
|
}
|
package/src/contracts/types.ts
CHANGED
|
@@ -57,6 +57,8 @@ export interface WorkspaceContext {
|
|
|
57
57
|
remoteConfigPath?: string;
|
|
58
58
|
/** Cached iOS SDK root used as the source for integration resources. */
|
|
59
59
|
iosSdkRoot?: string;
|
|
60
|
+
/** Optional cache root override, primarily used by tests. */
|
|
61
|
+
cacheRoot?: string;
|
|
60
62
|
android?: AndroidDetectResult;
|
|
61
63
|
/** Reserved: populated via placeholder until iOS tooling ships. */
|
|
62
64
|
ios?: IOSDetectResult;
|
|
@@ -72,6 +74,8 @@ export interface WorkspaceContextOptions {
|
|
|
72
74
|
remoteConfigPath?: string;
|
|
73
75
|
/** Override the iOS SDK source root. */
|
|
74
76
|
iosSdkRoot?: string;
|
|
77
|
+
/** Override meet-sdk-tool cache root. */
|
|
78
|
+
cacheRoot?: string;
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
export interface ManifestStep {
|
package/src/core/doctor.ts
CHANGED
|
@@ -198,6 +198,8 @@ async function checkAndroid(ctx: WorkspaceContext, report: DoctorReport, config:
|
|
|
198
198
|
await loadMeetSdkDefaultConfigWithLatestAndroidVersion({
|
|
199
199
|
sdkHomeApiBaseUrl: ctx.sdkHomeApiBaseUrl,
|
|
200
200
|
packageRoot: ctx.packageRoot,
|
|
201
|
+
cacheRoot: ctx.cacheRoot,
|
|
202
|
+
channelType: config.channel,
|
|
201
203
|
})
|
|
202
204
|
);
|
|
203
205
|
const moduleGradleAbs = moduleBuildGradlePath(ctx);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
|
-
/** Default directory for
|
|
4
|
+
/** Default directory for expected dry-run patch artifacts. */
|
|
5
5
|
export function resolveDefaultPreviewPatchDir(packageRoot: string): string {
|
|
6
|
-
return path.join(packageRoot, "
|
|
6
|
+
return path.join(packageRoot, "fixtures", "expected-patches");
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Before writing a new patch under `
|
|
10
|
+
* Before writing a new patch under `fixtures/expected-patches/`, remove all existing files there
|
|
11
11
|
* so only the latest command output remains.
|
|
12
12
|
*/
|
|
13
13
|
export function clearPreviewPatchFilesIfTargetInside(packageRoot: string, patchFileAbs: string): void {
|
package/src/core/workspace.ts
CHANGED
|
@@ -24,6 +24,7 @@ export function buildWorkspaceContext(
|
|
|
24
24
|
sdkHomeApiBaseUrl: options.sdkHomeApiBaseUrl,
|
|
25
25
|
remoteConfigPath: options.remoteConfigPath,
|
|
26
26
|
iosSdkRoot: options.iosSdkRoot,
|
|
27
|
+
cacheRoot: options.cacheRoot,
|
|
27
28
|
android: detectAndroid(root, { appTarget: options.appTarget }),
|
|
28
29
|
ios: detectIOS(root, { appTarget: options.appTarget }),
|
|
29
30
|
iosReserved: iosToolingReserved,
|
package/src/index.ts
CHANGED
|
@@ -61,10 +61,8 @@ export {
|
|
|
61
61
|
loadBuiltInMeetSdkDefaultConfig,
|
|
62
62
|
loadMeetSdkDefaultConfigWithLatestAndroidVersion,
|
|
63
63
|
resolveMeetSdkAndroidConfigPath,
|
|
64
|
-
syncMeetSdkAndroidVersionToConfig,
|
|
65
64
|
} from "./config/meetSdkDefaultConfig.js";
|
|
66
65
|
export {
|
|
67
|
-
MEETSDK_IOS_CONFIG_FILENAME,
|
|
68
66
|
loadMeetSdkIosConfig,
|
|
69
67
|
resolveMeetSdkIosConfigPath,
|
|
70
68
|
syncMeetSdkIosVersionToConfig,
|
|
@@ -81,9 +79,13 @@ export {
|
|
|
81
79
|
} from "./config/topsdkFeatureModules.js";
|
|
82
80
|
export { clearPreviewPatchFilesIfTargetInside, resolveDefaultPreviewPatchDir } from "./core/previewPatches.js";
|
|
83
81
|
export {
|
|
82
|
+
MEETSDK_ANDROID_CONFIG_FILENAME,
|
|
83
|
+
MEETSDK_IOS_CONFIG_FILENAME,
|
|
84
84
|
MEET_SDK_TOOL_CACHE_ROOT,
|
|
85
85
|
ensureCacheRoot,
|
|
86
86
|
resolveIosSdkCacheLayout,
|
|
87
|
+
resolveMeetSdkAndroidConfigCachePath,
|
|
88
|
+
resolveMeetSdkIosConfigCachePath,
|
|
87
89
|
resolveRemoteConfigCachePath,
|
|
88
90
|
writeRemoteConfigCache,
|
|
89
91
|
} from "./cache.js";
|
|
@@ -108,7 +110,6 @@ export {
|
|
|
108
110
|
} from "./remote/topsdkDownloadSdkConfig.js";
|
|
109
111
|
export {
|
|
110
112
|
DEFAULT_IOS_SDK_PACKAGE_TYPE,
|
|
111
|
-
DEFAULT_IOS_SDK_PLUGINS,
|
|
112
113
|
buildSdkHomeDownloadUrl,
|
|
113
114
|
buildSdkHomeVersionUrl,
|
|
114
115
|
defaultSdkHomeApiBaseUrl,
|
|
@@ -118,6 +119,7 @@ export {
|
|
|
118
119
|
fetchSdkHomeIosDownloadUrl,
|
|
119
120
|
fetchSdkHomeIosVersion,
|
|
120
121
|
fetchSdkHomeVersions,
|
|
122
|
+
resolveIosSdkDownloadPluginsFromRemoteConfig,
|
|
121
123
|
resolveIosSdkRootFromDirectory,
|
|
122
124
|
resolveIosSdkZipFileName,
|
|
123
125
|
type DownloadIosSdkOptions,
|
package/src/mcp/service.ts
CHANGED
|
@@ -24,7 +24,6 @@ import { defaultTopSdkBaseUrl, fetchTopSdkDownloadSdkConfig, type TopSdkApiEnv }
|
|
|
24
24
|
import {
|
|
25
25
|
downloadIosSdkToBundled,
|
|
26
26
|
defaultSdkHomeApiBaseUrl,
|
|
27
|
-
resolveIosSdkDownloadPluginsFromRemoteConfig,
|
|
28
27
|
} from "../remote/sdkHomeDownload.js";
|
|
29
28
|
import { resolveRemoteConfigCachePath, writeRemoteConfigCache } from "../cache.js";
|
|
30
29
|
|
|
@@ -71,12 +70,13 @@ function ensureSinglePlatformContext(
|
|
|
71
70
|
projectRoot: string,
|
|
72
71
|
packageRoot: string,
|
|
73
72
|
appTarget?: string,
|
|
74
|
-
remoteConfigPath?: string
|
|
73
|
+
remoteConfigPath?: string,
|
|
74
|
+
cacheRoot?: string
|
|
75
75
|
): {
|
|
76
76
|
platform: DetectedPlatform;
|
|
77
77
|
ctx: ReturnType<typeof buildWorkspaceContext>;
|
|
78
78
|
} {
|
|
79
|
-
const detectedCtx = buildWorkspaceContext(projectRoot, packageRoot, { appTarget, remoteConfigPath });
|
|
79
|
+
const detectedCtx = buildWorkspaceContext(projectRoot, packageRoot, { appTarget, remoteConfigPath, cacheRoot });
|
|
80
80
|
const detected = detectSinglePlatform(detectedCtx);
|
|
81
81
|
if (!detected.ok) throw new Error(detected.error);
|
|
82
82
|
const platformCtx = platformContext(detectedCtx, detected.platform);
|
|
@@ -186,6 +186,7 @@ export async function meetgamesIntegrate(params: {
|
|
|
186
186
|
env?: TopSdkApiEnv;
|
|
187
187
|
appId?: string;
|
|
188
188
|
channelType?: string;
|
|
189
|
+
cacheRoot?: string;
|
|
189
190
|
dryRun: boolean;
|
|
190
191
|
}): Promise<{
|
|
191
192
|
dryRun: boolean;
|
|
@@ -203,7 +204,8 @@ export async function meetgamesIntegrate(params: {
|
|
|
203
204
|
projectRoot,
|
|
204
205
|
packageRoot,
|
|
205
206
|
resolveAppTarget(params),
|
|
206
|
-
resolveCachedRemoteConfigPath(params)
|
|
207
|
+
resolveCachedRemoteConfigPath(params),
|
|
208
|
+
params.cacheRoot
|
|
207
209
|
);
|
|
208
210
|
const { report, patch, binaryCopies } = await runPipeline(ctx, manifestForPlatform(manifest, platform), { dryRun: params.dryRun });
|
|
209
211
|
return {
|
|
@@ -224,6 +226,7 @@ export async function meetgamesSetup(params: {
|
|
|
224
226
|
appId?: string;
|
|
225
227
|
appSecret?: string;
|
|
226
228
|
channelType?: string;
|
|
229
|
+
cacheRoot?: string;
|
|
227
230
|
dryRun: boolean;
|
|
228
231
|
}): Promise<{
|
|
229
232
|
fetch: Awaited<ReturnType<typeof meetgamesFetchConfig>>;
|
|
@@ -232,7 +235,7 @@ export async function meetgamesSetup(params: {
|
|
|
232
235
|
const projectRoot = ensureProjectRoot(params.projectRoot);
|
|
233
236
|
const packageRoot = resolvePackageRoot();
|
|
234
237
|
const appTarget = resolveAppTarget(params);
|
|
235
|
-
const { platform } = ensureSinglePlatformContext(projectRoot, packageRoot, appTarget);
|
|
238
|
+
const { platform } = ensureSinglePlatformContext(projectRoot, packageRoot, appTarget, undefined, params.cacheRoot);
|
|
236
239
|
const fetch = await meetgamesFetchConfig({
|
|
237
240
|
projectRoot,
|
|
238
241
|
env: params.env,
|
|
@@ -241,10 +244,10 @@ export async function meetgamesSetup(params: {
|
|
|
241
244
|
channelType: params.channelType,
|
|
242
245
|
});
|
|
243
246
|
if (platform === "ios") {
|
|
244
|
-
const remote = tryParseAsMeetSdkRemoteConfig(JSON.parse(fs.readFileSync(fetch.outputPath, "utf8")) as unknown);
|
|
245
247
|
await downloadIosSdkToBundled(packageRoot, {
|
|
246
248
|
baseUrl: process.env.MEETGAMES_SDK_HOME_API_BASE_URL?.trim() || defaultSdkHomeApiBaseUrl,
|
|
247
|
-
|
|
249
|
+
remoteConfigPath: fetch.outputPath,
|
|
250
|
+
cacheRoot: params.cacheRoot,
|
|
248
251
|
});
|
|
249
252
|
}
|
|
250
253
|
const integrate = await meetgamesIntegrate({
|
|
@@ -253,6 +256,7 @@ export async function meetgamesSetup(params: {
|
|
|
253
256
|
env: params.env,
|
|
254
257
|
appId: params.appId,
|
|
255
258
|
channelType: params.channelType,
|
|
259
|
+
cacheRoot: params.cacheRoot,
|
|
256
260
|
dryRun: params.dryRun,
|
|
257
261
|
});
|
|
258
262
|
return { fetch, integrate };
|
package/src/ops/handlers.ts
CHANGED
|
@@ -146,6 +146,8 @@ export const opHandlers: Record<string, OpHandler> = {
|
|
|
146
146
|
await loadMeetSdkDefaultConfigWithLatestAndroidVersion({
|
|
147
147
|
sdkHomeApiBaseUrl: ctx.sdkHomeApiBaseUrl,
|
|
148
148
|
packageRoot: ctx.packageRoot,
|
|
149
|
+
cacheRoot: ctx.cacheRoot,
|
|
150
|
+
channelType: parsed.channel,
|
|
149
151
|
})
|
|
150
152
|
);
|
|
151
153
|
|
|
@@ -302,6 +304,8 @@ export const opHandlers: Record<string, OpHandler> = {
|
|
|
302
304
|
await loadMeetSdkDefaultConfigWithLatestAndroidVersion({
|
|
303
305
|
sdkHomeApiBaseUrl: ctx.sdkHomeApiBaseUrl,
|
|
304
306
|
packageRoot: ctx.packageRoot,
|
|
307
|
+
cacheRoot: ctx.cacheRoot,
|
|
308
|
+
channelType: parsed.channel,
|
|
305
309
|
})
|
|
306
310
|
);
|
|
307
311
|
const firebase = resolved.sdkModules.analytics.firebase;
|