@leonxin/meetgames 0.1.18 → 0.1.20

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.
Files changed (109) hide show
  1. package/README.md +16 -6
  2. package/dist/android/detect.d.ts +6 -1
  3. package/dist/android/detect.d.ts.map +1 -1
  4. package/dist/android/detect.js +41 -17
  5. package/dist/android/detect.js.map +1 -1
  6. package/dist/android/gradle.d.ts.map +1 -1
  7. package/dist/android/gradle.js +8 -1
  8. package/dist/android/gradle.js.map +1 -1
  9. package/dist/android/meetSdkRemoteGradle.d.ts +1 -0
  10. package/dist/android/meetSdkRemoteGradle.d.ts.map +1 -1
  11. package/dist/android/meetSdkRemoteGradle.js +44 -21
  12. package/dist/android/meetSdkRemoteGradle.js.map +1 -1
  13. package/dist/cache.d.ts +16 -0
  14. package/dist/cache.d.ts.map +1 -1
  15. package/dist/cache.js +21 -0
  16. package/dist/cache.js.map +1 -1
  17. package/dist/cli.d.ts.map +1 -1
  18. package/dist/cli.js +52 -23
  19. package/dist/cli.js.map +1 -1
  20. package/dist/config/meetSdkDefaultConfig.d.ts +7 -11
  21. package/dist/config/meetSdkDefaultConfig.d.ts.map +1 -1
  22. package/dist/config/meetSdkDefaultConfig.js +216 -53
  23. package/dist/config/meetSdkDefaultConfig.js.map +1 -1
  24. package/dist/config/meetSdkIosConfig.d.ts +4 -5
  25. package/dist/config/meetSdkIosConfig.d.ts.map +1 -1
  26. package/dist/config/meetSdkIosConfig.js +19 -19
  27. package/dist/config/meetSdkIosConfig.js.map +1 -1
  28. package/dist/contracts/types.d.ts +18 -0
  29. package/dist/contracts/types.d.ts.map +1 -1
  30. package/dist/core/doctor.d.ts.map +1 -1
  31. package/dist/core/doctor.js +18 -1
  32. package/dist/core/doctor.js.map +1 -1
  33. package/dist/core/platform.js +1 -1
  34. package/dist/core/platform.js.map +1 -1
  35. package/dist/core/previewPatches.d.ts +2 -2
  36. package/dist/core/previewPatches.d.ts.map +1 -1
  37. package/dist/core/previewPatches.js +3 -3
  38. package/dist/core/previewPatches.js.map +1 -1
  39. package/dist/core/workspace.d.ts.map +1 -1
  40. package/dist/core/workspace.js +3 -1
  41. package/dist/core/workspace.js.map +1 -1
  42. package/dist/index.d.ts +4 -4
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +4 -4
  45. package/dist/index.js.map +1 -1
  46. package/dist/mcp/server.d.ts.map +1 -1
  47. package/dist/mcp/server.js +12 -7
  48. package/dist/mcp/server.js.map +1 -1
  49. package/dist/mcp/service.d.ts +6 -0
  50. package/dist/mcp/service.d.ts.map +1 -1
  51. package/dist/mcp/service.js +17 -9
  52. package/dist/mcp/service.js.map +1 -1
  53. package/dist/ops/handlers.d.ts.map +1 -1
  54. package/dist/ops/handlers.js +25 -3
  55. package/dist/ops/handlers.js.map +1 -1
  56. package/dist/remote/sdkHomeDownload.d.ts +4 -5
  57. package/dist/remote/sdkHomeDownload.d.ts.map +1 -1
  58. package/dist/remote/sdkHomeDownload.js +38 -12
  59. package/dist/remote/sdkHomeDownload.js.map +1 -1
  60. package/docs/API.md +13 -13
  61. package/docs/CLI.md +27 -13
  62. package/docs/INTEGRATION.md +7 -6
  63. package/package.json +1 -1
  64. package/src/android/detect.ts +47 -17
  65. package/src/android/gradle.ts +16 -1
  66. package/src/android/meetSdkRemoteGradle.ts +50 -22
  67. package/src/cache.ts +37 -0
  68. package/src/cli.ts +51 -21
  69. package/src/config/meetSdkDefaultConfig.ts +243 -59
  70. package/src/config/meetSdkIosConfig.ts +17 -21
  71. package/src/contracts/types.ts +21 -0
  72. package/src/core/doctor.ts +17 -1
  73. package/src/core/platform.ts +1 -1
  74. package/src/core/previewPatches.ts +3 -3
  75. package/src/core/workspace.ts +3 -1
  76. package/src/index.ts +5 -3
  77. package/src/mcp/server.ts +12 -7
  78. package/src/mcp/service.ts +30 -10
  79. package/src/ops/handlers.ts +27 -3
  80. package/src/remote/sdkHomeDownload.ts +48 -16
  81. package/config/meetsdk-android.json +0 -171
  82. package/config/meetsdk-ios.json +0 -15
  83. package/tests/assemble.test.ts +0 -12
  84. package/tests/doctor.test.ts +0 -131
  85. package/tests/downloadGoogleServicesJson.test.ts +0 -47
  86. package/tests/fetch-remote.test.ts +0 -23
  87. package/tests/fetchConfigOverrides.test.ts +0 -28
  88. package/tests/fetchConfigWrite.test.ts +0 -54
  89. package/tests/fixtures-hosts.test.ts +0 -78
  90. package/tests/gradle.test.ts +0 -33
  91. package/tests/integration-json.test.ts +0 -29
  92. package/tests/ios.codeUtils.test.ts +0 -23
  93. package/tests/ios.sdkBundle.test.ts +0 -21
  94. package/tests/loadManifest.test.ts +0 -15
  95. package/tests/manifest-xml.test.ts +0 -30
  96. package/tests/mcp.e2e.ts +0 -214
  97. package/tests/mcp.service.test.ts +0 -53
  98. package/tests/meetSdkRemoteConfig.test.ts +0 -482
  99. package/tests/meetSdkRemoteGradle.test.ts +0 -414
  100. package/tests/pipeline.android.test.ts +0 -149
  101. package/tests/pipeline.integration-json.test.ts +0 -58
  102. package/tests/pipeline.ios.test.ts +0 -609
  103. package/tests/pipeline.preview.patch.test.ts +0 -85
  104. package/tests/platformSelection.test.ts +0 -77
  105. package/tests/sdkHomeDownload.test.ts +0 -275
  106. package/tests/sdkVersionConfig.test.ts +0 -131
  107. package/tests/topsdk.test.ts +0 -53
  108. package/tests/topsdkDownloadSdkConfig.test.ts +0 -81
  109. package/tests/topsdkFeatureModules.test.ts +0 -116
package/src/mcp/server.ts CHANGED
@@ -31,11 +31,12 @@ export function createMeetgamesMcpServer(): McpServer {
31
31
  inputSchema: {
32
32
  projectRoot: z.string().optional().describe("Absolute or relative project root; default is current working directory."),
33
33
  appTarget: z.string().optional().describe("App target to integrate/check: Android application Gradle module or iOS App target name."),
34
+ sdkModuleName: z.string().optional().describe("Android SDK integration Gradle module for resValue/dependencies; default is unityLibrary."),
34
35
  },
35
36
  },
36
- async ({ projectRoot, appTarget }) => {
37
+ async ({ projectRoot, appTarget, sdkModuleName }) => {
37
38
  try {
38
- return toSuccessResult(meetgamesDoctor({ projectRoot, appTarget }));
39
+ return toSuccessResult(meetgamesDoctor({ projectRoot, appTarget, sdkModuleName }));
39
40
  } catch (error) {
40
41
  return toErrorResult(error);
41
42
  }
@@ -78,14 +79,15 @@ export function createMeetgamesMcpServer(): McpServer {
78
79
  inputSchema: {
79
80
  projectRoot: z.string().optional().describe("Absolute or relative project root; default is current working directory."),
80
81
  appTarget: z.string().optional().describe("App target to integrate/check: Android application Gradle module or iOS App target name."),
82
+ sdkModuleName: z.string().optional().describe("Android SDK integration Gradle module for resValue/dependencies; default is unityLibrary."),
81
83
  env: z.enum(["prod", "pre", "test"]).optional().describe("TOPSDK API environment for selecting cached config."),
82
84
  appId: z.string().optional().describe("Application id for selecting cached config."),
83
85
  channelType: z.string().optional().describe("Channel type for selecting cached config."),
84
86
  },
85
87
  },
86
- async ({ projectRoot, appTarget, env, appId, channelType }) => {
88
+ async ({ projectRoot, appTarget, sdkModuleName, env, appId, channelType }) => {
87
89
  try {
88
- const result = await meetgamesIntegrate({ projectRoot, appTarget, env, appId, channelType, dryRun: true });
90
+ const result = await meetgamesIntegrate({ projectRoot, appTarget, sdkModuleName, env, appId, channelType, dryRun: true });
89
91
  if (result.hasErrors) {
90
92
  return {
91
93
  ...toSuccessResult(result),
@@ -106,14 +108,15 @@ export function createMeetgamesMcpServer(): McpServer {
106
108
  inputSchema: {
107
109
  projectRoot: z.string().optional().describe("Absolute or relative project root; default is current working directory."),
108
110
  appTarget: z.string().optional().describe("App target to integrate/check: Android application Gradle module or iOS App target name."),
111
+ sdkModuleName: z.string().optional().describe("Android SDK integration Gradle module for resValue/dependencies; default is unityLibrary."),
109
112
  env: z.enum(["prod", "pre", "test"]).optional().describe("TOPSDK API environment for selecting cached config."),
110
113
  appId: z.string().optional().describe("Application id for selecting cached config."),
111
114
  channelType: z.string().optional().describe("Channel type for selecting cached config."),
112
115
  },
113
116
  },
114
- async ({ projectRoot, appTarget, env, appId, channelType }) => {
117
+ async ({ projectRoot, appTarget, sdkModuleName, env, appId, channelType }) => {
115
118
  try {
116
- const result = await meetgamesIntegrate({ projectRoot, appTarget, env, appId, channelType, dryRun: false });
119
+ const result = await meetgamesIntegrate({ projectRoot, appTarget, sdkModuleName, env, appId, channelType, dryRun: false });
117
120
  if (result.hasErrors) {
118
121
  return {
119
122
  ...toSuccessResult(result),
@@ -139,14 +142,16 @@ export function createMeetgamesMcpServer(): McpServer {
139
142
  appSecret: z.string().optional().describe("Application secret for downloadSDKConfig sign (required unless TOPSDK_APP_SECRET is set)."),
140
143
  channelType: z.string().optional().describe("Channel type e.g. GOOGLE; required if not in local config."),
141
144
  appTarget: z.string().optional().describe("App target to integrate/check: Android application Gradle module or iOS App target name."),
145
+ sdkModuleName: z.string().optional().describe("Android SDK integration Gradle module for resValue/dependencies; default is unityLibrary."),
142
146
  dryRun: z.boolean().optional().describe("If true, integrate step previews only; fetch always writes config."),
143
147
  },
144
148
  },
145
- async ({ projectRoot, env, appId, appSecret, channelType, appTarget, dryRun }) => {
149
+ async ({ projectRoot, env, appId, appSecret, channelType, appTarget, sdkModuleName, dryRun }) => {
146
150
  try {
147
151
  const result = await meetgamesSetup({
148
152
  projectRoot,
149
153
  appTarget,
154
+ sdkModuleName,
150
155
  env,
151
156
  appId,
152
157
  appSecret,
@@ -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,14 @@ function ensureSinglePlatformContext(
71
70
  projectRoot: string,
72
71
  packageRoot: string,
73
72
  appTarget?: string,
74
- remoteConfigPath?: string
73
+ sdkModuleName?: string,
74
+ remoteConfigPath?: string,
75
+ cacheRoot?: string
75
76
  ): {
76
77
  platform: DetectedPlatform;
77
78
  ctx: ReturnType<typeof buildWorkspaceContext>;
78
79
  } {
79
- const detectedCtx = buildWorkspaceContext(projectRoot, packageRoot, { appTarget, remoteConfigPath });
80
+ const detectedCtx = buildWorkspaceContext(projectRoot, packageRoot, { appTarget, sdkModuleName, remoteConfigPath, cacheRoot });
80
81
  const detected = detectSinglePlatform(detectedCtx);
81
82
  if (!detected.ok) throw new Error(detected.error);
82
83
  const platformCtx = platformContext(detectedCtx, detected.platform);
@@ -90,11 +91,16 @@ function resolveAppTarget(params: { appTarget?: string }): string | undefined {
90
91
  return params.appTarget?.trim() || undefined;
91
92
  }
92
93
 
93
- export function meetgamesDoctor(params: { projectRoot?: string; appTarget?: string }): {
94
+ function resolveSdkModuleName(params: { sdkModuleName?: string }): string | undefined {
95
+ return params.sdkModuleName?.trim() || undefined;
96
+ }
97
+
98
+ export function meetgamesDoctor(params: { projectRoot?: string; appTarget?: string; sdkModuleName?: string }): {
94
99
  projectRoot: string;
95
100
  packageRoot: string;
96
101
  platform: DetectedPlatform;
97
102
  android?: object;
103
+ androidSdkModule?: object;
98
104
  ios?: object;
99
105
  iosReserved?: object;
100
106
  } {
@@ -103,13 +109,15 @@ export function meetgamesDoctor(params: { projectRoot?: string; appTarget?: stri
103
109
  const { platform, ctx } = ensureSinglePlatformContext(
104
110
  projectRoot,
105
111
  packageRoot,
106
- resolveAppTarget(params)
112
+ resolveAppTarget(params),
113
+ resolveSdkModuleName(params)
107
114
  );
108
115
  const out: {
109
116
  projectRoot: string;
110
117
  packageRoot: string;
111
118
  platform: DetectedPlatform;
112
119
  android?: object;
120
+ androidSdkModule?: object;
113
121
  ios?: object;
114
122
  iosReserved?: object;
115
123
  } = {
@@ -117,7 +125,10 @@ export function meetgamesDoctor(params: { projectRoot?: string; appTarget?: stri
117
125
  packageRoot: ctx.packageRoot,
118
126
  platform,
119
127
  };
120
- if (platform === "android") out.android = ctx.android;
128
+ if (platform === "android") {
129
+ out.android = ctx.android;
130
+ out.androidSdkModule = ctx.androidSdkModule;
131
+ }
121
132
  if (platform === "ios") {
122
133
  out.ios = ctx.ios;
123
134
  out.iosReserved = ctx.iosReserved;
@@ -183,9 +194,11 @@ export async function meetgamesFetchConfig(params: {
183
194
  export async function meetgamesIntegrate(params: {
184
195
  projectRoot?: string;
185
196
  appTarget?: string;
197
+ sdkModuleName?: string;
186
198
  env?: TopSdkApiEnv;
187
199
  appId?: string;
188
200
  channelType?: string;
201
+ cacheRoot?: string;
189
202
  dryRun: boolean;
190
203
  }): Promise<{
191
204
  dryRun: boolean;
@@ -203,7 +216,9 @@ export async function meetgamesIntegrate(params: {
203
216
  projectRoot,
204
217
  packageRoot,
205
218
  resolveAppTarget(params),
206
- resolveCachedRemoteConfigPath(params)
219
+ resolveSdkModuleName(params),
220
+ resolveCachedRemoteConfigPath(params),
221
+ params.cacheRoot
207
222
  );
208
223
  const { report, patch, binaryCopies } = await runPipeline(ctx, manifestForPlatform(manifest, platform), { dryRun: params.dryRun });
209
224
  return {
@@ -220,10 +235,12 @@ export async function meetgamesIntegrate(params: {
220
235
  export async function meetgamesSetup(params: {
221
236
  projectRoot?: string;
222
237
  appTarget?: string;
238
+ sdkModuleName?: string;
223
239
  env?: TopSdkApiEnv;
224
240
  appId?: string;
225
241
  appSecret?: string;
226
242
  channelType?: string;
243
+ cacheRoot?: string;
227
244
  dryRun: boolean;
228
245
  }): Promise<{
229
246
  fetch: Awaited<ReturnType<typeof meetgamesFetchConfig>>;
@@ -232,7 +249,8 @@ export async function meetgamesSetup(params: {
232
249
  const projectRoot = ensureProjectRoot(params.projectRoot);
233
250
  const packageRoot = resolvePackageRoot();
234
251
  const appTarget = resolveAppTarget(params);
235
- const { platform } = ensureSinglePlatformContext(projectRoot, packageRoot, appTarget);
252
+ const sdkModuleName = resolveSdkModuleName(params);
253
+ const { platform } = ensureSinglePlatformContext(projectRoot, packageRoot, appTarget, sdkModuleName, undefined, params.cacheRoot);
236
254
  const fetch = await meetgamesFetchConfig({
237
255
  projectRoot,
238
256
  env: params.env,
@@ -241,18 +259,20 @@ export async function meetgamesSetup(params: {
241
259
  channelType: params.channelType,
242
260
  });
243
261
  if (platform === "ios") {
244
- const remote = tryParseAsMeetSdkRemoteConfig(JSON.parse(fs.readFileSync(fetch.outputPath, "utf8")) as unknown);
245
262
  await downloadIosSdkToBundled(packageRoot, {
246
263
  baseUrl: process.env.MEETGAMES_SDK_HOME_API_BASE_URL?.trim() || defaultSdkHomeApiBaseUrl,
247
- plugins: remote ? resolveIosSdkDownloadPluginsFromRemoteConfig(remote) : undefined,
264
+ remoteConfigPath: fetch.outputPath,
265
+ cacheRoot: params.cacheRoot,
248
266
  });
249
267
  }
250
268
  const integrate = await meetgamesIntegrate({
251
269
  projectRoot,
252
270
  appTarget,
271
+ sdkModuleName,
253
272
  env: params.env,
254
273
  appId: params.appId,
255
274
  channelType: params.channelType,
275
+ cacheRoot: params.cacheRoot,
256
276
  dryRun: params.dryRun,
257
277
  });
258
278
  return { fetch, integrate };
@@ -85,8 +85,8 @@ function readSettingsGradle(projectRoot: string): { rel: string; abs: string } |
85
85
  }
86
86
 
87
87
  function moduleGradleRel(ctx: WorkspaceContext): string | null {
88
- if (!ctx.android?.ok) return null;
89
- const moduleDir = ctx.android.moduleDir;
88
+ if (!ctx.androidSdkModule?.ok) return null;
89
+ const moduleDir = ctx.androidSdkModule.moduleDir;
90
90
  const a = path.join(moduleDir, "build.gradle");
91
91
  if (fs.existsSync(a)) return path.relative(ctx.projectRoot, a).split(path.sep).join("/");
92
92
  const b = path.join(moduleDir, "build.gradle.kts");
@@ -94,6 +94,20 @@ function moduleGradleRel(ctx: WorkspaceContext): string | null {
94
94
  return null;
95
95
  }
96
96
 
97
+ function sdkModuleError(ctx: WorkspaceContext): string {
98
+ return ctx.androidSdkModule?.ok === false
99
+ ? ctx.androidSdkModule.error
100
+ : "android SDK module not resolved";
101
+ }
102
+
103
+ function sdkModuleIsApplicationModule(ctx: WorkspaceContext): boolean {
104
+ return Boolean(
105
+ ctx.android?.ok &&
106
+ ctx.androidSdkModule?.ok &&
107
+ path.resolve(ctx.android.moduleDir) === path.resolve(ctx.androidSdkModule.moduleDir)
108
+ );
109
+ }
110
+
97
111
  function resolveRemoteConfigInput(ctx: WorkspaceContext, configFile: unknown): { abs: string; label: string } {
98
112
  if (typeof configFile === "string" && configFile.trim()) {
99
113
  const normalized = configFile.trim().replace(/\\/g, "/");
@@ -127,6 +141,7 @@ export const opHandlers: Record<string, OpHandler> = {
127
141
  */
128
142
  "gradle.applyMeetSdkRemoteConfig": async (ctx, store, args, _dry, _bc) => {
129
143
  if (!ctx.android?.ok) return fail(["android application module not detected"]);
144
+ if (!ctx.androidSdkModule?.ok) return fail([sdkModuleError(ctx)]);
130
145
  const config = resolveRemoteConfigInput(ctx, args.configFile);
131
146
  if (!fs.existsSync(config.abs)) return fail([`meet sdk remote config not found: ${config.label}`]);
132
147
  let raw: unknown;
@@ -146,6 +161,8 @@ export const opHandlers: Record<string, OpHandler> = {
146
161
  await loadMeetSdkDefaultConfigWithLatestAndroidVersion({
147
162
  sdkHomeApiBaseUrl: ctx.sdkHomeApiBaseUrl,
148
163
  packageRoot: ctx.packageRoot,
164
+ cacheRoot: ctx.cacheRoot,
165
+ channelType: parsed.channel,
149
166
  })
150
167
  );
151
168
 
@@ -195,9 +212,12 @@ export const opHandlers: Record<string, OpHandler> = {
195
212
  return fail(["gradle.applyMeetSdkRemoteConfig: root build.gradle.kts not supported in MVP"]);
196
213
  }
197
214
  const rootBefore = store.read(root.rel);
215
+ const shouldMirrorRepositoriesToBuildscript = /\bbuildscript\s*\{/.test(rootBefore) || buildscriptClasspaths.length > 0;
198
216
  const rootU = updateRootBuildGradleMeetSdkRemote(rootBefore, {
199
217
  repositories: repositoriesWrittenInSettings ? [] : repositories,
200
- buildscriptRepositories: usesPluginsDsl ? [] : buildscriptRepositories,
218
+ buildscriptRepositories: usesPluginsDsl
219
+ ? []
220
+ : [...buildscriptRepositories, ...(shouldMirrorRepositoriesToBuildscript ? repositories : [])],
201
221
  buildscriptClasspaths: usesPluginsDsl ? [] : buildscriptClasspaths,
202
222
  rootPluginsDsl: usesPluginsDsl ? collectMeetSdkRemotePluginsDslForRoot(resolved) : [],
203
223
  stripBuildscriptClasspaths: usesPluginsDsl ? buildscriptClasspaths : [],
@@ -213,6 +233,7 @@ export const opHandlers: Record<string, OpHandler> = {
213
233
  style: modulePluginStyle,
214
234
  applyPlugins: usesPluginsDsl ? [] : collectMeetSdkRemoteApplyPlugins(resolved),
215
235
  pluginsDsl: usesPluginsDsl ? collectMeetSdkRemotePluginsDslForModule(resolved) : [],
236
+ writeApplicationId: sdkModuleIsApplicationModule(ctx),
216
237
  });
217
238
  if (!modU.ok) return fail([modU.error]);
218
239
 
@@ -241,6 +262,7 @@ export const opHandlers: Record<string, OpHandler> = {
241
262
 
242
263
  "gradle.addDependency": (ctx, store, args, _dry, _bc) => {
243
264
  if (!ctx.android?.ok) return fail(["android application module not detected"]);
265
+ if (!ctx.androidSdkModule?.ok) return fail([sdkModuleError(ctx)]);
244
266
  const modRel = moduleGradleRel(ctx);
245
267
  if (!modRel) return fail(["module build.gradle not found"]);
246
268
  if (modRel.endsWith(".kts")) return fail(["gradle.addDependency: build.gradle.kts not supported in MVP"]);
@@ -302,6 +324,8 @@ export const opHandlers: Record<string, OpHandler> = {
302
324
  await loadMeetSdkDefaultConfigWithLatestAndroidVersion({
303
325
  sdkHomeApiBaseUrl: ctx.sdkHomeApiBaseUrl,
304
326
  packageRoot: ctx.packageRoot,
327
+ cacheRoot: ctx.cacheRoot,
328
+ channelType: parsed.channel,
305
329
  })
306
330
  );
307
331
  const firebase = resolved.sdkModules.analytics.firebase;
@@ -2,11 +2,15 @@ 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
+ import {
6
+ MEETSDK_REMOTE_CONFIG_FILENAME,
7
+ hasSdkModuleKey,
8
+ tryParseAsMeetSdkRemoteConfig,
9
+ type MeetSdkRemoteConfig,
10
+ } from "../config/meetSdkRemoteConfig.js";
6
11
  import { resolveIosSdkCacheLayout, withCacheLock, writeIosSdkCacheMetadata } from "../cache.js";
7
12
 
8
13
  export const defaultSdkHomeApiBaseUrl = "https://business-api.meetgames.com";
9
- export const DEFAULT_IOS_SDK_PLUGINS = ["guest", "facebook", "google", "apple", "apple_pay", "dataAppsFlyer"] as const;
10
14
  export const DEFAULT_IOS_SDK_PACKAGE_TYPE = "native";
11
15
 
12
16
  const IOS_SDK_DOWNLOAD_PLUGIN_BY_SUBKEY: Record<string, string> = {
@@ -47,14 +51,14 @@ export interface SdkHomeVersions {
47
51
  export interface SdkHomeDownloadUrlRequest {
48
52
  baseUrl: string;
49
53
  version: string;
50
- platform?: "ios";
51
- plugins?: readonly string[] | string;
54
+ platform?: "ios" | "android";
55
+ plugins: readonly string[] | string;
52
56
  packageType?: string;
53
57
  }
54
58
 
55
59
  export interface DownloadIosSdkOptions {
56
60
  baseUrl?: string;
57
- plugins?: readonly string[] | string;
61
+ remoteConfigPath: string;
58
62
  packageType?: string;
59
63
  cacheRoot?: string;
60
64
  signal?: AbortSignal;
@@ -83,16 +87,22 @@ function joinBaseAndPath(baseUrl: string, subPath: string): URL {
83
87
  return new URL(subPath, base);
84
88
  }
85
89
 
86
- function pluginsToCsv(plugins: readonly string[] | string | undefined): string {
87
- if (typeof plugins === "string") return plugins;
88
- return (plugins ?? DEFAULT_IOS_SDK_PLUGINS).join(",");
90
+ function normalizeDownloadPlugins(plugins: readonly string[] | string): string[] {
91
+ const list = (typeof plugins === "string" ? plugins.split(",") : plugins)
92
+ .map((s) => String(s).trim())
93
+ .filter(Boolean);
94
+ if (!list.length) {
95
+ throw new Error(`SDK download plugins must be resolved before requesting sdk-home`);
96
+ }
97
+ return list;
89
98
  }
90
99
 
91
- function pluginsToList(plugins: readonly string[] | string | undefined): string[] {
92
- return pluginsToCsv(plugins)
93
- .split(",")
94
- .map((s) => s.trim())
95
- .filter(Boolean);
100
+ function pluginsToCsv(plugins: readonly string[] | string): string {
101
+ return normalizeDownloadPlugins(plugins).join(",");
102
+ }
103
+
104
+ function pluginsToList(plugins: readonly string[] | string): string[] {
105
+ return normalizeDownloadPlugins(plugins);
96
106
  }
97
107
 
98
108
  export function resolveIosSdkDownloadPluginsFromRemoteConfig(config: MeetSdkRemoteConfig): string[] {
@@ -109,6 +119,28 @@ export function resolveIosSdkDownloadPluginsFromRemoteConfig(config: MeetSdkRemo
109
119
  return [...new Set(plugins)];
110
120
  }
111
121
 
122
+ function readIosSdkDownloadPluginsFromRemoteConfigFile(configPath: string): string[] {
123
+ if (!configPath || !fs.existsSync(configPath)) {
124
+ throw new Error(`iOS ${MEETSDK_REMOTE_CONFIG_FILENAME} not found: ${configPath || MEETSDK_REMOTE_CONFIG_FILENAME}`);
125
+ }
126
+ let raw: unknown;
127
+ try {
128
+ raw = JSON.parse(fs.readFileSync(configPath, "utf8")) as unknown;
129
+ } catch {
130
+ throw new Error(`failed to parse iOS ${MEETSDK_REMOTE_CONFIG_FILENAME}: ${configPath}`);
131
+ }
132
+ const remote = tryParseAsMeetSdkRemoteConfig(raw);
133
+ if (!remote) throw new Error(`not a ${MEETSDK_REMOTE_CONFIG_FILENAME} document: ${configPath}`);
134
+ if (remote.devicePlatform !== "ios") {
135
+ throw new Error(`iOS SDK download requires an iOS ${MEETSDK_REMOTE_CONFIG_FILENAME}: ${configPath}`);
136
+ }
137
+ const plugins = resolveIosSdkDownloadPluginsFromRemoteConfig(remote);
138
+ if (!plugins.length) {
139
+ throw new Error(`iOS ${MEETSDK_REMOTE_CONFIG_FILENAME} does not enable any sdk-home iOS plugins: ${configPath}`);
140
+ }
141
+ return plugins;
142
+ }
143
+
112
144
  export function buildSdkHomeVersionUrl(baseUrl: string): string {
113
145
  return joinBaseAndPath(baseUrl, SDK_HOME_VERSION_PATH).toString();
114
146
  }
@@ -329,11 +361,11 @@ export async function extractZip(zipPath: string, destDir: string): Promise<void
329
361
 
330
362
  export async function downloadIosSdkToBundled(
331
363
  packageRoot: string,
332
- options: DownloadIosSdkOptions = {}
364
+ options: DownloadIosSdkOptions
333
365
  ): Promise<DownloadIosSdkResult> {
334
366
  const baseUrl = options.baseUrl || defaultSdkHomeApiBaseUrl;
335
367
  const packageType = options.packageType || DEFAULT_IOS_SDK_PACKAGE_TYPE;
336
- const plugins = pluginsToList(options.plugins);
368
+ const plugins = readIosSdkDownloadPluginsFromRemoteConfigFile(options.remoteConfigPath);
337
369
  const versionResult = await fetchSdkHomeIosVersion({ baseUrl, signal: options.signal });
338
370
  const serverVersion = versionResult.ios.ver;
339
371
  const reusableCache = findReusableCachedIosSdk({
@@ -370,7 +402,7 @@ export async function downloadIosSdkToBundled(
370
402
  };
371
403
  await withCacheLock(cacheLayout.lockDir, downloadAndExtract);
372
404
  const iosConfigPath = syncMeetSdkIosVersionToConfig({
373
- packageRoot,
405
+ cacheRoot: options.cacheRoot,
374
406
  version,
375
407
  date: versionResult.ios.date,
376
408
  packageType,
@@ -1,171 +0,0 @@
1
- {
2
- "topsdk": {
3
- "version": "1.6.1.3",
4
- "date": "2026-05-25",
5
- "groupId": "com.sino.topsdk",
6
- "repositories": [
7
- "https://storage-sdk-gameplus.meetsocial.com/repository/TopSdk/"
8
- ]
9
- },
10
- "sdkModules": {
11
- "login": {
12
- "guest": {
13
- "dependencies": [
14
- {
15
- "implementation": "$groupId:guest:$topsdk_version"
16
- }
17
- ]
18
- },
19
- "email": {
20
- "dependencies": [
21
- {
22
- "implementation": "$groupId:email:$topsdk_version"
23
- }
24
- ]
25
- },
26
- "facebook": {
27
- "dependencies": [
28
- {
29
- "implementation": "$groupId:facebook:$topsdk_version"
30
- }
31
- ]
32
- },
33
- "google": {
34
- "dependencies": [
35
- {
36
- "implementation": "$groupId:google:$topsdk_version"
37
- }
38
- ]
39
- },
40
- "twitter": {
41
- "dependencies": [
42
- {
43
- "implementation": "$groupId:twitter:$topsdk_version"
44
- }
45
- ]
46
- },
47
- "snapchat": {
48
- "dependencies": [
49
- {
50
- "implementation": "$groupId:snapchat:$topsdk_version"
51
- }
52
- ]
53
- },
54
- "line": {
55
- "dependencies": [
56
- {
57
- "implementation": "$groupId:line:$topsdk_version"
58
- }
59
- ]
60
- },
61
- "naver": {
62
- "dependencies": [
63
- {
64
- "implementation": "$groupId:naver:$topsdk_version"
65
- }
66
- ]
67
- },
68
- "kakao": {
69
- "repositories": [
70
- "https://devrepo.kakao.com/nexus/content/groups/public/"
71
- ],
72
- "dependencies": [
73
- {
74
- "implementation": "$groupId:kakao:$topsdk_version"
75
- }
76
- ]
77
- },
78
- "tiktok": {
79
- "repositories": [
80
- "https://artifact.bytedance.com/repository/AwemeOpenSDK"
81
- ],
82
- "dependencies": [
83
- {
84
- "implementation": "$groupId:tiktok:$topsdk_version"
85
- }
86
- ]
87
- },
88
- "discord": {
89
- "dependencies": [
90
- {
91
- "implementation": "$groupId:discord:$topsdk_version"
92
- }
93
- ]
94
- }
95
- },
96
- "payment": {
97
- "googleIap": {
98
- "dependencies": [
99
- {
100
- "implementation": "$groupId:google-iap:$topsdk_version"
101
- }
102
- ]
103
- },
104
- "onestoreIap": {
105
- "repositories": [
106
- "https://repo.onestore.co.kr/repository/onestore-sdk-public/"
107
- ],
108
- "dependencies": [
109
- {
110
- "implementation": "$groupId:onestore-iap:$topsdk_version"
111
- }
112
- ]
113
- },
114
- "huaweiIap": {
115
- "repositories": [
116
- "https://developer.huawei.com/repo/"
117
- ],
118
- "dependencies": [
119
- {
120
- "implementation": "$groupId:huawei-iap:$topsdk_version"
121
- }
122
- ]
123
- },
124
- "xiaomiIap": {
125
- "dependencies": [
126
- {
127
- "implementation": "$groupId:xiaomi-iap:$topsdk_version"
128
- }
129
- ]
130
- }
131
- },
132
- "analytics": {
133
- "appsflyer": {
134
- "repositories": [
135
- "mavenCentral"
136
- ],
137
- "dependencies": [
138
- {
139
- "implementation": "$groupId:appsflyer:$topsdk_version"
140
- }
141
- ]
142
- },
143
- "facebookdata": {
144
- "dependencies": [
145
- {
146
- "implementation": "$groupId:facebook-data:$topsdk_version"
147
- }
148
- ]
149
- },
150
- "firebase": {
151
- "repositories": [
152
- "google"
153
- ],
154
- "classpath": "com.google.gms:google-services:4.4.4",
155
- "applyplugin": "com.google.gms.google-services",
156
- "dependencies": [
157
- {
158
- "implementation": "$groupId:firebase:$topsdk_version"
159
- }
160
- ]
161
- },
162
- "adjust": {
163
- "dependencies": [
164
- {
165
- "implementation": "$groupId:adjust:$topsdk_version"
166
- }
167
- ]
168
- }
169
- }
170
- }
171
- }
@@ -1,15 +0,0 @@
1
- {
2
- "topsdk": {
3
- "version": "99.88.78-cache-test",
4
- "date": "2026-06-26",
5
- "packageType": "native",
6
- "plugins": [
7
- "guest",
8
- "facebook",
9
- "google",
10
- "apple",
11
- "apple_pay",
12
- "dataAppsFlyer"
13
- ]
14
- }
15
- }
@@ -1,12 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { unwrapRemoteIntegrationPayload } from "../src/android/assembleIntegrationJson.js";
3
-
4
- describe("assembleIntegrationJson", () => {
5
- it("unwraps common envelopes", () => {
6
- const inner = { version: 1, steps: [{ op: "gradle.insertRepositories", args: { urls: ["mavenCentral"] } }] };
7
- expect(unwrapRemoteIntegrationPayload(inner)).toBe(inner);
8
- expect(unwrapRemoteIntegrationPayload({ data: inner })).toEqual(inner);
9
- expect(unwrapRemoteIntegrationPayload({ config: inner })).toEqual(inner);
10
- expect(unwrapRemoteIntegrationPayload({ android: inner })).toEqual(inner);
11
- });
12
- });