@leonxin/meetgames 0.1.7 → 0.1.11

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 (293) hide show
  1. package/.agents/skills/meet-sdk-regression/SKILL.md +93 -0
  2. package/.cursor/mcp.example.json +16 -0
  3. package/.cursor/mcp.json +11 -0
  4. package/.cursor/skills/meetgames-mcp/SKILL.md +48 -0
  5. package/.vite/vitest/results.json +1 -0
  6. package/README.md +31 -8
  7. package/dist/aab-converter/aab-entry.d.ts +3 -0
  8. package/dist/aab-converter/aab-entry.d.ts.map +1 -0
  9. package/dist/aab-converter/aab-entry.js +49 -0
  10. package/dist/aab-converter/aab-entry.js.map +1 -0
  11. package/dist/aab-converter/apksExtractor.d.ts +2 -0
  12. package/dist/aab-converter/apksExtractor.d.ts.map +1 -0
  13. package/dist/aab-converter/apksExtractor.js +108 -0
  14. package/dist/aab-converter/apksExtractor.js.map +1 -0
  15. package/dist/aab-converter/bundletoolRunner.d.ts +15 -0
  16. package/dist/aab-converter/bundletoolRunner.d.ts.map +1 -0
  17. package/dist/aab-converter/bundletoolRunner.js +46 -0
  18. package/dist/aab-converter/bundletoolRunner.js.map +1 -0
  19. package/dist/aab-converter/cliArgs.d.ts +27 -0
  20. package/dist/aab-converter/cliArgs.d.ts.map +1 -0
  21. package/dist/aab-converter/cliArgs.js +170 -0
  22. package/dist/aab-converter/cliArgs.js.map +1 -0
  23. package/dist/aab-converter/convertAabToApk.d.ts +7 -0
  24. package/dist/aab-converter/convertAabToApk.d.ts.map +1 -0
  25. package/dist/aab-converter/convertAabToApk.js +69 -0
  26. package/dist/aab-converter/convertAabToApk.js.map +1 -0
  27. package/dist/aab-converter/resourcePaths.d.ts +4 -0
  28. package/dist/aab-converter/resourcePaths.d.ts.map +1 -0
  29. package/dist/aab-converter/resourcePaths.js +42 -0
  30. package/dist/aab-converter/resourcePaths.js.map +1 -0
  31. package/dist/aab-converter/signingOptions.d.ts +9 -0
  32. package/dist/aab-converter/signingOptions.d.ts.map +1 -0
  33. package/dist/aab-converter/signingOptions.js +21 -0
  34. package/dist/aab-converter/signingOptions.js.map +1 -0
  35. package/dist/aab-converter/types.d.ts +24 -0
  36. package/dist/aab-converter/types.d.ts.map +1 -0
  37. package/dist/aab-converter/types.js +2 -0
  38. package/dist/aab-converter/types.js.map +1 -0
  39. package/dist/android/adapter.d.ts.map +1 -1
  40. package/dist/android/adapter.js +2 -2
  41. package/dist/android/adapter.js.map +1 -1
  42. package/dist/android/detect.d.ts +2 -2
  43. package/dist/android/detect.d.ts.map +1 -1
  44. package/dist/android/detect.js +36 -8
  45. package/dist/android/detect.js.map +1 -1
  46. package/dist/android/meetSdkRemoteGradle.d.ts +0 -3
  47. package/dist/android/meetSdkRemoteGradle.d.ts.map +1 -1
  48. package/dist/android/meetSdkRemoteGradle.js +13 -20
  49. package/dist/android/meetSdkRemoteGradle.js.map +1 -1
  50. package/dist/cli.d.ts.map +1 -1
  51. package/dist/cli.js +157 -31
  52. package/dist/cli.js.map +1 -1
  53. package/dist/config/meetSdkDefaultConfig.d.ts +19 -2
  54. package/dist/config/meetSdkDefaultConfig.d.ts.map +1 -1
  55. package/dist/config/meetSdkDefaultConfig.js +67 -5
  56. package/dist/config/meetSdkDefaultConfig.js.map +1 -1
  57. package/dist/config/meetSdkIosConfig.d.ts +21 -0
  58. package/dist/config/meetSdkIosConfig.d.ts.map +1 -0
  59. package/dist/config/meetSdkIosConfig.js +66 -0
  60. package/dist/config/meetSdkIosConfig.js.map +1 -0
  61. package/dist/config/meetSdkRemoteConfig.d.ts +19 -11
  62. package/dist/config/meetSdkRemoteConfig.d.ts.map +1 -1
  63. package/dist/config/meetSdkRemoteConfig.js +89 -69
  64. package/dist/config/meetSdkRemoteConfig.js.map +1 -1
  65. package/dist/config/topsdkFeatureModules.d.ts +5 -0
  66. package/dist/config/topsdkFeatureModules.d.ts.map +1 -1
  67. package/dist/config/topsdkFeatureModules.js +26 -0
  68. package/dist/config/topsdkFeatureModules.js.map +1 -1
  69. package/dist/contracts/types.d.ts +19 -6
  70. package/dist/contracts/types.d.ts.map +1 -1
  71. package/dist/core/doctor.d.ts +17 -0
  72. package/dist/core/doctor.d.ts.map +1 -0
  73. package/dist/core/doctor.js +444 -0
  74. package/dist/core/doctor.js.map +1 -0
  75. package/dist/core/pipeline.d.ts.map +1 -1
  76. package/dist/core/pipeline.js +0 -15
  77. package/dist/core/pipeline.js.map +1 -1
  78. package/dist/core/platform.d.ts +12 -0
  79. package/dist/core/platform.d.ts.map +1 -0
  80. package/dist/core/platform.js +40 -0
  81. package/dist/core/platform.js.map +1 -0
  82. package/dist/core/reporter.js +1 -1
  83. package/dist/core/reporter.js.map +1 -1
  84. package/dist/core/workspace.d.ts +2 -2
  85. package/dist/core/workspace.d.ts.map +1 -1
  86. package/dist/core/workspace.js +4 -5
  87. package/dist/core/workspace.js.map +1 -1
  88. package/dist/index.d.ts +3 -1
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +3 -1
  91. package/dist/index.js.map +1 -1
  92. package/dist/ios/channelConfig.d.ts +1 -0
  93. package/dist/ios/channelConfig.d.ts.map +1 -1
  94. package/dist/ios/channelConfig.js +82 -0
  95. package/dist/ios/channelConfig.js.map +1 -1
  96. package/dist/ios/codeUtils.d.ts +1 -0
  97. package/dist/ios/codeUtils.d.ts.map +1 -1
  98. package/dist/ios/codeUtils.js +11 -2
  99. package/dist/ios/codeUtils.js.map +1 -1
  100. package/dist/ios/detect.d.ts +2 -2
  101. package/dist/ios/detect.d.ts.map +1 -1
  102. package/dist/ios/detect.js +49 -10
  103. package/dist/ios/detect.js.map +1 -1
  104. package/dist/ios/entitlements.d.ts +4 -0
  105. package/dist/ios/entitlements.d.ts.map +1 -0
  106. package/dist/ios/entitlements.js +53 -0
  107. package/dist/ios/entitlements.js.map +1 -0
  108. package/dist/ios/fileManager.d.ts.map +1 -1
  109. package/dist/ios/fileManager.js +3 -2
  110. package/dist/ios/fileManager.js.map +1 -1
  111. package/dist/ios/infoPlist.d.ts +1 -1
  112. package/dist/ios/infoPlist.d.ts.map +1 -1
  113. package/dist/ios/infoPlist.js.map +1 -1
  114. package/dist/ios/integrate.d.ts.map +1 -1
  115. package/dist/ios/integrate.js +211 -36
  116. package/dist/ios/integrate.js.map +1 -1
  117. package/dist/ios/pbxprojEditor.d.ts +2 -0
  118. package/dist/ios/pbxprojEditor.d.ts.map +1 -1
  119. package/dist/ios/pbxprojEditor.js +179 -1
  120. package/dist/ios/pbxprojEditor.js.map +1 -1
  121. package/dist/ios/pluginConfig.d.ts +1 -0
  122. package/dist/ios/pluginConfig.d.ts.map +1 -1
  123. package/dist/ios/pluginConfig.js +36 -4
  124. package/dist/ios/pluginConfig.js.map +1 -1
  125. package/dist/ios/sdkBundle.d.ts +1 -1
  126. package/dist/ios/sdkBundle.d.ts.map +1 -1
  127. package/dist/ios/sdkBundle.js +7 -5
  128. package/dist/ios/sdkBundle.js.map +1 -1
  129. package/dist/ios/template.d.ts +1 -0
  130. package/dist/ios/template.d.ts.map +1 -1
  131. package/dist/ios/template.js +14 -1
  132. package/dist/ios/template.js.map +1 -1
  133. package/dist/ios/types.d.ts +2 -2
  134. package/dist/ios/types.d.ts.map +1 -1
  135. package/dist/mcp/server.d.ts.map +1 -1
  136. package/dist/mcp/server.js +14 -13
  137. package/dist/mcp/server.js.map +1 -1
  138. package/dist/mcp/service.d.ts +8 -6
  139. package/dist/mcp/service.d.ts.map +1 -1
  140. package/dist/mcp/service.js +34 -14
  141. package/dist/mcp/service.js.map +1 -1
  142. package/dist/ops/handlers.d.ts.map +1 -1
  143. package/dist/ops/handlers.js +10 -4
  144. package/dist/ops/handlers.js.map +1 -1
  145. package/dist/remote/sdkHomeDownload.d.ts +65 -0
  146. package/dist/remote/sdkHomeDownload.d.ts.map +1 -0
  147. package/dist/remote/sdkHomeDownload.js +208 -0
  148. package/dist/remote/sdkHomeDownload.js.map +1 -0
  149. package/dist/remote/topsdkDownloadSdkConfig.d.ts.map +1 -1
  150. package/dist/remote/topsdkDownloadSdkConfig.js +11 -1
  151. package/dist/remote/topsdkDownloadSdkConfig.js.map +1 -1
  152. package/dist/shared/errors.d.ts +7 -0
  153. package/dist/shared/errors.d.ts.map +1 -0
  154. package/dist/shared/errors.js +16 -0
  155. package/dist/shared/errors.js.map +1 -0
  156. package/dist/shared/fileUtils.d.ts +5 -0
  157. package/dist/shared/fileUtils.d.ts.map +1 -0
  158. package/dist/shared/fileUtils.js +35 -0
  159. package/dist/shared/fileUtils.js.map +1 -0
  160. package/dist/shared/logger.d.ts +10 -0
  161. package/dist/shared/logger.d.ts.map +1 -0
  162. package/dist/shared/logger.js +37 -0
  163. package/dist/shared/logger.js.map +1 -0
  164. package/dist/shared/pathUtils.d.ts +4 -0
  165. package/dist/shared/pathUtils.d.ts.map +1 -0
  166. package/dist/shared/pathUtils.js +22 -0
  167. package/dist/shared/pathUtils.js.map +1 -0
  168. package/dist/shared/processRunner.d.ts +12 -0
  169. package/dist/shared/processRunner.d.ts.map +1 -0
  170. package/dist/shared/processRunner.js +31 -0
  171. package/dist/shared/processRunner.js.map +1 -0
  172. package/docs/AAB_CONVERTER_CLI_PLAN.md +392 -0
  173. package/docs/API.md +246 -32
  174. package/docs/CLI.md +292 -0
  175. package/docs/INTEGRATION.md +116 -0
  176. package/docs/MCP.md +86 -0
  177. package/docs/README.md +19 -10
  178. package/docs/{api → archive/api}/downloadSDKConfig.md +8 -6
  179. package/docs/{api → archive/api}/getChannelConfig-meetgames.md +1 -1
  180. package/docs/archive/ios-migration.md +2139 -0
  181. package/docs/{ → archive/product/}/346/212/200/346/234/257/346/226/271/346/241/210/350/260/203/347/240/224.md +7 -7
  182. package/docs/{ → archive/product/}/351/234/200/346/261/202/346/226/207/346/241/243.md +15 -14
  183. package/logs/convert-20260622-155037.log +5 -0
  184. package/logs/convert-20260622-155226.log +6 -0
  185. package/meetsdk-android.json +2 -1
  186. package/meetsdk-ios.json +15 -0
  187. package/package.json +10 -35
  188. package/scripts/package-aab-cli-win.mjs +193 -0
  189. package/src/aab-converter/aab-entry.ts +48 -0
  190. package/src/aab-converter/apksExtractor.ts +119 -0
  191. package/src/aab-converter/bundletoolRunner.ts +63 -0
  192. package/src/aab-converter/cliArgs.ts +194 -0
  193. package/src/aab-converter/convertAabToApk.ts +81 -0
  194. package/src/aab-converter/resourcePaths.ts +43 -0
  195. package/src/aab-converter/signingOptions.ts +29 -0
  196. package/src/aab-converter/types.ts +26 -0
  197. package/src/android/adapter.ts +9 -0
  198. package/src/android/assembleIntegrationJson.ts +33 -0
  199. package/src/android/detect.ts +132 -0
  200. package/src/android/downloadGoogleServicesJson.ts +56 -0
  201. package/src/android/gradle.ts +116 -0
  202. package/src/android/manifest.ts +50 -0
  203. package/src/android/meetSdkRemoteGradle.ts +837 -0
  204. package/src/cli.ts +488 -0
  205. package/src/config/fetchConfigWrite.ts +30 -0
  206. package/src/config/loadAndroidIntegration.ts +41 -0
  207. package/src/config/loadManifest.ts +40 -0
  208. package/src/config/meetSdkDefaultConfig.ts +99 -0
  209. package/src/config/meetSdkIosConfig.ts +87 -0
  210. package/src/config/meetSdkRemoteConfig.ts +1211 -0
  211. package/src/config/topsdkFeatureModules.ts +92 -0
  212. package/src/contracts/types.ts +121 -0
  213. package/src/core/doctor.ts +485 -0
  214. package/src/core/patch.ts +64 -0
  215. package/src/core/pipeline.ts +107 -0
  216. package/src/core/platform.ts +47 -0
  217. package/src/core/previewPatches.ts +23 -0
  218. package/src/core/reporter.ts +24 -0
  219. package/src/core/workspace.ts +29 -0
  220. package/src/entry.ts +7 -0
  221. package/src/index.ts +133 -0
  222. package/src/ios/channelConfig.ts +128 -0
  223. package/src/ios/codeUtils.ts +160 -0
  224. package/src/ios/detect.ts +105 -0
  225. package/src/ios/entitlements.ts +61 -0
  226. package/src/ios/fileManager.ts +48 -0
  227. package/src/ios/infoPlist.ts +55 -0
  228. package/src/ios/integrate.ts +516 -0
  229. package/src/ios/pbxprojEditor.ts +383 -0
  230. package/src/ios/pluginConfig.ts +97 -0
  231. package/src/ios/reserved.ts +8 -0
  232. package/src/ios/sdkBundle.ts +36 -0
  233. package/src/ios/template.ts +36 -0
  234. package/src/ios/types.ts +65 -0
  235. package/src/mcp/server.ts +170 -0
  236. package/src/mcp/service.ts +222 -0
  237. package/src/mcp-entry.ts +7 -0
  238. package/src/ops/fileStore.ts +56 -0
  239. package/src/ops/handlers.ts +304 -0
  240. package/src/remote/fetchJson.ts +22 -0
  241. package/src/remote/sdkHomeDownload.ts +274 -0
  242. package/src/remote/topsdkDownloadSdkConfig.ts +93 -0
  243. package/src/remote/topsdkGetSdkConfig.ts +122 -0
  244. package/src/remote/topsdkSign.ts +10 -0
  245. package/src/shared/errors.ts +16 -0
  246. package/src/shared/fileUtils.ts +41 -0
  247. package/src/shared/logger.ts +49 -0
  248. package/src/shared/pathUtils.ts +24 -0
  249. package/src/shared/processRunner.ts +43 -0
  250. package/test-projects/README.md +51 -0
  251. package/test-projects/_preview/pipeline.patch +281 -0
  252. package/tests/aab-converter.test.ts +213 -0
  253. package/tests/assemble.test.ts +12 -0
  254. package/tests/doctor.test.ts +89 -0
  255. package/tests/downloadGoogleServicesJson.test.ts +47 -0
  256. package/tests/fetch-remote.test.ts +23 -0
  257. package/tests/fetchConfigOverrides.test.ts +28 -0
  258. package/tests/fetchConfigWrite.test.ts +54 -0
  259. package/tests/gradle.test.ts +33 -0
  260. package/tests/integration-json.test.ts +29 -0
  261. package/tests/ios.codeUtils.test.ts +23 -0
  262. package/tests/ios.sdkBundle.test.ts +16 -0
  263. package/tests/loadManifest.test.ts +15 -0
  264. package/tests/manifest-xml.test.ts +30 -0
  265. package/tests/mcp.e2e.ts +217 -0
  266. package/tests/mcp.service.test.ts +53 -0
  267. package/tests/meetSdkRemoteConfig.test.ts +456 -0
  268. package/tests/meetSdkRemoteGradle.test.ts +414 -0
  269. package/tests/pipeline.android.test.ts +96 -0
  270. package/tests/pipeline.integration-json.test.ts +58 -0
  271. package/tests/pipeline.ios.test.ts +385 -0
  272. package/tests/pipeline.preview.patch.test.ts +85 -0
  273. package/tests/platformSelection.test.ts +77 -0
  274. package/tests/sdkHomeDownload.test.ts +124 -0
  275. package/tests/sdkVersionConfig.test.ts +130 -0
  276. package/tests/test-projects-hosts.test.ts +78 -0
  277. package/tests/topsdk.test.ts +53 -0
  278. package/tests/topsdkDownloadSdkConfig.test.ts +81 -0
  279. package/tests/topsdkFeatureModules.test.ts +116 -0
  280. package/tsconfig.json +19 -0
  281. package/vitest.config.ts +9 -0
  282. package/vitest.mcp.config.ts +11 -0
  283. package/bundled/android/sample.txt +0 -1
  284. package/docs/ANDROID.md +0 -133
  285. package/docs/CURSOR-MCP-SETUP.md +0 -72
  286. package/docs/MCP-SKILL.md +0 -63
  287. package/fixtures/api-samples/getChannelConfig-meetgames.sample.json +0 -123
  288. package/fixtures/meetsdk-remote-config.download-shape.json +0 -20
  289. package/fixtures/meetsdk-remote-config.mock.json +0 -69
  290. package/fixtures/recipes/android-default.fixture.yaml +0 -15
  291. package/fixtures/recipes/android-integration.fixture.json +0 -29
  292. package/fixtures/topsdk-config-reference.json +0 -39
  293. /package/docs/{api → archive/api}/getSDKConfig.md +0 -0
@@ -0,0 +1,456 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { describe, expect, it } from "vitest";
5
+ import {
6
+ applyMeetSdkDefaultConfig,
7
+ collectMeetSdkRemoteRepositories,
8
+ mapTopSdkGetSdkConfigToMeetSdkRemoteConfig,
9
+ tryParseAsMeetSdkRemoteConfig,
10
+ validateMeetSdkRemoteConfig,
11
+ } from "../src/config/meetSdkRemoteConfig.js";
12
+ import { loadBuiltInMeetSdkDefaultConfig } from "../src/config/meetSdkDefaultConfig.js";
13
+
14
+ const here = path.dirname(fileURLToPath(import.meta.url));
15
+ const refPath = path.join(here, "..", "fixtures", "topsdk-config-reference.json");
16
+ const offlineMockPath = path.join(here, "..", "fixtures", "meetsdk-remote-config.mock.json");
17
+ const offlineIosMockPath = path.join(here, "..", "fixtures", "meetsdk-remote-config.ios-tooltest.json");
18
+ const downloadShapePath = path.join(here, "..", "fixtures", "meetsdk-remote-config.download-shape.json");
19
+
20
+ const mapCtx = {
21
+ appId: "app-1",
22
+ appSecret: "test-secret",
23
+ channelType: "google",
24
+ packageName: "com.example.pkg",
25
+ };
26
+
27
+ describe("meetSdkRemoteConfig", () => {
28
+ it("parses downloadSDKConfig shape (root channel, no topsdk.channel)", () => {
29
+ const raw = JSON.parse(fs.readFileSync(downloadShapePath, "utf8")) as unknown;
30
+ const parsed = tryParseAsMeetSdkRemoteConfig(raw);
31
+ expect(parsed).not.toBeNull();
32
+ expect(parsed?.channel).toBe("GOOGLE");
33
+ expect(parsed?.devicePlatform).toBe("android");
34
+ expect(parsed?.topsdk).not.toHaveProperty("channel");
35
+ expect(validateMeetSdkRemoteConfig(parsed!).ok).toBe(true);
36
+ const login = parsed!.sdkModules.login as unknown as Record<string, unknown>;
37
+ expect(login.google).toBeDefined();
38
+ expect(login.kakao).toBeUndefined();
39
+ expect("kakao" in login).toBe(false);
40
+ });
41
+
42
+ it("parses downloadSDKConfig DTO field names directly", () => {
43
+ const parsed = tryParseAsMeetSdkRemoteConfig({
44
+ packageName: "com.example",
45
+ channel: "APPLE",
46
+ devicePlatform: "ios",
47
+ topsdk: { appId: "1", appSecret: "s" },
48
+ sdkModules: {
49
+ login: {
50
+ facebook: { clientId: "fb-app", scheme: "fb-scheme", secret: "fb-token", name: "FB Name" },
51
+ google: { clientId: "google-client", scheme: "google-reversed" },
52
+ snapchat: { clientId: "snap-client", redirect: "snap-redirect", scheme: "snap-scheme" },
53
+ naver: { clientId: "naver-client", secret: "naver-secret", name: "Naver", scheme: "naver-scheme" },
54
+ apple: {},
55
+ },
56
+ payment: {},
57
+ analytics: {
58
+ appsflyer: { devKey: "af-key", appleAppId: "1234567890" },
59
+ firebase: { firebaseUrl: "https://cdn.example/GoogleService-Info.plist", firebaseName: "GoogleService-Info.plist" },
60
+ adjust: { appCode: "adjust-token" },
61
+ },
62
+ },
63
+ });
64
+
65
+ expect(parsed).not.toBeNull();
66
+ expect(parsed!.sdkModules.login.facebook).toMatchObject({
67
+ facebookAppId: "fb-app",
68
+ fbLoginProtocolScheme: "fb-scheme",
69
+ facebookClientToken: "fb-token",
70
+ name: "FB Name",
71
+ });
72
+ expect(parsed!.sdkModules.login.google).toMatchObject({
73
+ googleClientId: "google-client",
74
+ scheme: "google-reversed",
75
+ });
76
+ expect(parsed!.sdkModules.analytics.firebase).toMatchObject({
77
+ firebase_file_url: "https://cdn.example/GoogleService-Info.plist",
78
+ firebase_file_name: "GoogleService-Info.plist",
79
+ });
80
+ expect(parsed!.sdkModules.analytics.adjust).toMatchObject({ appId: "adjust-token" });
81
+ expect(parsed!.sdkModules.analytics.appsflyer).toMatchObject({
82
+ devKey: "af-key",
83
+ appleAppId: "1234567890",
84
+ });
85
+ });
86
+
87
+ it("does not treat legacy remote field names as valid config", () => {
88
+ const parsed = tryParseAsMeetSdkRemoteConfig({
89
+ packageName: "com.example",
90
+ channel: "GOOGLE",
91
+ devicePlatform: "android",
92
+ topsdk: { appId: "1", appSecret: "s" },
93
+ sdkModules: {
94
+ login: {
95
+ facebook: {
96
+ facebookAppId: "fb-app",
97
+ fbLoginProtocolScheme: "fb-scheme",
98
+ facebookClientToken: "fb-token",
99
+ },
100
+ google: { googleClientId: "google-client" },
101
+ },
102
+ payment: {},
103
+ analytics: {
104
+ firebase: { firebase_file_url: "https://cdn.example/google-services.json" },
105
+ adjust: { appId: "adjust-token" },
106
+ },
107
+ },
108
+ });
109
+
110
+ expect(parsed).not.toBeNull();
111
+ expect(validateMeetSdkRemoteConfig(parsed!)).toMatchObject({
112
+ ok: false,
113
+ missing: expect.arrayContaining([
114
+ "sdkModules.login.facebook.clientId",
115
+ "sdkModules.login.facebook.scheme",
116
+ "sdkModules.login.facebook.secret",
117
+ "sdkModules.login.google.clientId",
118
+ "sdkModules.analytics.firebase.firebaseUrl",
119
+ "sdkModules.analytics.adjust.appCode",
120
+ ]),
121
+ });
122
+ });
123
+
124
+ it("parses reference mock shape", () => {
125
+ const raw = JSON.parse(fs.readFileSync(refPath, "utf8")) as unknown;
126
+ const parsed = tryParseAsMeetSdkRemoteConfig(raw);
127
+ expect(parsed).not.toBeNull();
128
+ expect(parsed?.channel).toBe("GOOGLE");
129
+ expect(parsed?.devicePlatform).toBe("android");
130
+ expect(parsed?.topsdk).not.toHaveProperty("channel");
131
+ expect(validateMeetSdkRemoteConfig(parsed!).ok).toBe(true);
132
+ const resolved = applyMeetSdkDefaultConfig(parsed!, loadBuiltInMeetSdkDefaultConfig());
133
+ expect(resolved.topsdk.repositories).toContain("https://storage-sdk-gameplus.meetsocial.com/repository/TopSdk/");
134
+ });
135
+
136
+ it("offline meetsdk-remote-config.mock.json is valid for local testing", () => {
137
+ const raw = JSON.parse(fs.readFileSync(offlineMockPath, "utf8")) as unknown;
138
+ const parsed = tryParseAsMeetSdkRemoteConfig(raw);
139
+ expect(parsed).not.toBeNull();
140
+ expect(parsed?.channel).toBe("GOOGLE");
141
+ expect(parsed?.devicePlatform).toBe("android");
142
+ expect(validateMeetSdkRemoteConfig(parsed!).ok).toBe(true);
143
+ });
144
+
145
+ it("offline iOS remote config fixture is valid for local testing", () => {
146
+ const raw = JSON.parse(fs.readFileSync(offlineIosMockPath, "utf8")) as unknown;
147
+ const parsed = tryParseAsMeetSdkRemoteConfig(raw);
148
+ expect(parsed).not.toBeNull();
149
+ expect(parsed?.channel).toBe("APPLE");
150
+ expect(parsed?.devicePlatform).toBe("ios");
151
+ expect(validateMeetSdkRemoteConfig(parsed!).ok).toBe(true);
152
+ });
153
+
154
+ it("rejects sdkModules.login.kakao when value is false (not object)", () => {
155
+ const raw = {
156
+ packageName: "com.example",
157
+ channel: "GOOGLE",
158
+ topsdk: { appId: "1", appSecret: "s" },
159
+ sdkModules: { login: { kakao: false }, payment: {}, analytics: {} },
160
+ };
161
+ expect(tryParseAsMeetSdkRemoteConfig(raw)).toBeNull();
162
+ });
163
+
164
+ it("rejects legacy file with topsdk.channel only", () => {
165
+ const raw = {
166
+ packageName: "com.legacy.app",
167
+ topsdk: { channel: "GOOGLE", appId: "1", appSecret: "s" },
168
+ sdkModules: { login: {}, payment: {}, analytics: {} },
169
+ };
170
+ expect(tryParseAsMeetSdkRemoteConfig(raw)).toBeNull();
171
+ });
172
+
173
+ it("maps getSDKConfig envelope to nested sdkModules credentials", () => {
174
+ const body = {
175
+ code: 200,
176
+ data: {
177
+ appId: "app-1",
178
+ groupId: "com.sino.topsdk",
179
+ sdkVersion: "1.2.3",
180
+ repositories: ["google", "mavenCentral"],
181
+ channelAuthConfig: [
182
+ { authType: "GOOGLE", clientId: "google-cid" },
183
+ { authType: "FACEBOOK", clientId: "fbid", scheme: "fbfbid", clientToken: "ctok" },
184
+ { authType: "APPSFLYER", devKey: "afkey", enableDebugLog: true },
185
+ ],
186
+ },
187
+ };
188
+ const meet = mapTopSdkGetSdkConfigToMeetSdkRemoteConfig(body, mapCtx);
189
+ expect(meet.packageName).toBe("com.example.pkg");
190
+ expect(meet.channel).toBe("GOOGLE");
191
+ expect(meet.topsdk.appSecret).toBe("test-secret");
192
+ expect(meet.topsdk).toMatchObject({
193
+ version: "1.2.3",
194
+ groupId: "com.sino.topsdk",
195
+ appId: "app-1",
196
+ appSecret: "test-secret",
197
+ repositories: ["google", "mavenCentral"],
198
+ });
199
+ expect(meet.topsdk).not.toHaveProperty("channel");
200
+ expect(meet.sdkModules.login.google).toMatchObject({ googleClientId: "google-cid" });
201
+ expect(meet.sdkModules.login.facebook).toMatchObject({
202
+ facebookAppId: "fbid",
203
+ fbLoginProtocolScheme: "fbfbid",
204
+ facebookClientToken: "ctok",
205
+ });
206
+ expect(meet.sdkModules.analytics.appsflyer).toMatchObject({
207
+ devKey: "afkey",
208
+ enableDebugLog: true,
209
+ });
210
+ });
211
+
212
+ it("maps gp-sdk VO-shaped channelAuth (secret as Facebook client token and AppsFlyer devKey)", () => {
213
+ const body = {
214
+ code: 200,
215
+ data: {
216
+ channelAuthConfig: [
217
+ { authType: "FACEBOOK", clientId: "fb-app", scheme: "fbfb-app", secret: "client-token-from-secret" },
218
+ { authType: "APPSFLYER", clientId: "apple-app-id-field", secret: "real-dev-key" },
219
+ ],
220
+ },
221
+ };
222
+ const meet = mapTopSdkGetSdkConfigToMeetSdkRemoteConfig(body, {
223
+ appId: "99",
224
+ appSecret: "s",
225
+ channelType: "google",
226
+ packageName: "com.p",
227
+ });
228
+ expect(meet.sdkModules.login.facebook).toMatchObject({
229
+ facebookAppId: "fb-app",
230
+ fbLoginProtocolScheme: "fbfb-app",
231
+ facebookClientToken: "client-token-from-secret",
232
+ });
233
+ expect(meet.sdkModules.analytics.appsflyer).toMatchObject({
234
+ devKey: "real-dev-key",
235
+ enableDebugLog: false,
236
+ });
237
+ });
238
+
239
+ it("maps TWITTER / LINE / KAKAO from channelAuthConfig", () => {
240
+ const body = {
241
+ code: 200,
242
+ data: {
243
+ channelAuthConfig: [
244
+ { authType: "TWITTER", clientId: "tw-cid", secret: "tw-sec", redirect: "https://cb" },
245
+ { authType: "LINE", clientId: "line-ch" },
246
+ { authType: "KAKAO", clientId: "kakao-key", scheme: "kakaokey" },
247
+ ],
248
+ },
249
+ };
250
+ const meet = mapTopSdkGetSdkConfigToMeetSdkRemoteConfig(body, mapCtx);
251
+ expect(meet.sdkModules.login.twitter).toMatchObject({
252
+ clientId: "tw-cid",
253
+ secret: "tw-sec",
254
+ redirect: "https://cb",
255
+ });
256
+ expect(meet.sdkModules.login.line).toMatchObject({ clientId: "line-ch" });
257
+ expect(meet.sdkModules.login.kakao).toMatchObject({ clientId: "kakao-key", scheme: "kakaokey" });
258
+ });
259
+
260
+ it("maps FIREBASE and ADJUST channelAuthConfig", () => {
261
+ const body = {
262
+ code: 200,
263
+ data: {
264
+ channelAuthConfig: [
265
+ { authType: "FIREBASE", firebase_file_url: "https://cdn.example/google-services.json" },
266
+ { authType: "ADJUST", appId: "adj-app-1" },
267
+ ],
268
+ },
269
+ };
270
+ const meet = mapTopSdkGetSdkConfigToMeetSdkRemoteConfig(body, mapCtx);
271
+ expect(meet.sdkModules.analytics.firebase).toMatchObject({
272
+ firebase_file_url: "https://cdn.example/google-services.json",
273
+ });
274
+ expect(meet.sdkModules.analytics.adjust).toMatchObject({ appId: "adj-app-1" });
275
+ });
276
+
277
+ it("maps FIREBASE firebase_file_url from configUrl fallback", () => {
278
+ const body = {
279
+ code: 200,
280
+ data: {
281
+ channelAuthConfig: [{ authType: "FIREBASE", configUrl: "https://u/g.json" }],
282
+ },
283
+ };
284
+ const meet = mapTopSdkGetSdkConfigToMeetSdkRemoteConfig(body, mapCtx);
285
+ expect(meet.sdkModules.analytics.firebase).toMatchObject({
286
+ firebase_file_url: "https://u/g.json",
287
+ });
288
+ });
289
+
290
+ it("prefers data.topsdk.version and groupId when nested object is present", () => {
291
+ const body = {
292
+ code: 200,
293
+ data: {
294
+ sdkVersion: "1.0.0",
295
+ topsdk: { version: "2.0.0", groupId: "com.x" },
296
+ channelAuthConfig: [],
297
+ },
298
+ };
299
+ const meet = mapTopSdkGetSdkConfigToMeetSdkRemoteConfig(body, mapCtx);
300
+ expect(meet.topsdk.version).toBe("2.0.0");
301
+ expect(meet.topsdk.groupId).toBe("com.x");
302
+ });
303
+
304
+ it("rejects top-level parameterConfig", () => {
305
+ const raw = {
306
+ packageName: "x",
307
+ topsdk: { channel: "GOOGLE", version: "1", groupId: "g", appId: "a", appSecret: "s" },
308
+ parameterConfig: { id: "1" },
309
+ sdkModules: {
310
+ login: {},
311
+ payment: {},
312
+ analytics: {},
313
+ },
314
+ };
315
+ expect(tryParseAsMeetSdkRemoteConfig(raw)).toBeNull();
316
+ });
317
+
318
+ it("rejects deprecated sdkModules.login.parameterConfig", () => {
319
+ const raw = {
320
+ packageName: "x",
321
+ topsdk: { channel: "GOOGLE", version: "1", groupId: "g", appId: "a", appSecret: "s" },
322
+ sdkModules: {
323
+ login: {
324
+ parameterConfig: { id: "1" },
325
+ },
326
+ payment: {},
327
+ analytics: {},
328
+ },
329
+ };
330
+ expect(tryParseAsMeetSdkRemoteConfig(raw)).toBeNull();
331
+ });
332
+
333
+ it("rejects deprecated sdkModules.login.parameter", () => {
334
+ const raw = {
335
+ packageName: "x",
336
+ topsdk: { channel: "GOOGLE", version: "1", groupId: "g", appId: "a", appSecret: "s" },
337
+ sdkModules: {
338
+ login: { parameter: { id: "1" } },
339
+ payment: {},
340
+ analytics: {},
341
+ },
342
+ };
343
+ expect(tryParseAsMeetSdkRemoteConfig(raw)).toBeNull();
344
+ });
345
+
346
+ it("rejects legacy flat features without sdkModules", () => {
347
+ const raw = {
348
+ packageName: "x",
349
+ topsdk: { channel: "GOOGLE", version: "1", groupId: "g", appId: "a", appSecret: "s" },
350
+ features: { guest: false, email: false, facebook: true, google: false, appsflyer: false, googleIap: false },
351
+ };
352
+ expect(tryParseAsMeetSdkRemoteConfig(raw)).toBeNull();
353
+ });
354
+
355
+ it("accepts root channel without topsdk.channel", () => {
356
+ const raw = {
357
+ channel: "GOOGLE",
358
+ packageName: "x",
359
+ topsdk: { version: "1", groupId: "g", appId: "a", appSecret: "s" },
360
+ sdkModules: {
361
+ login: {},
362
+ payment: {},
363
+ analytics: {},
364
+ },
365
+ };
366
+ const parsed = tryParseAsMeetSdkRemoteConfig(raw);
367
+ expect(parsed).not.toBeNull();
368
+ expect(parsed?.channel).toBe("GOOGLE");
369
+ expect(parsed?.topsdk).not.toHaveProperty("channel");
370
+ });
371
+
372
+ it("rejects top-level facebook/google/appsflyer (credentials belong under sdkModules)", () => {
373
+ const raw = {
374
+ packageName: "x",
375
+ topsdk: { channel: "GOOGLE", version: "1", groupId: "g", appId: "a", appSecret: "s" },
376
+ facebook: { facebookAppId: "x", fbLoginProtocolScheme: "y", facebookClientToken: "z" },
377
+ sdkModules: {
378
+ login: {},
379
+ payment: {},
380
+ analytics: {},
381
+ },
382
+ };
383
+ expect(tryParseAsMeetSdkRemoteConfig(raw)).toBeNull();
384
+ });
385
+
386
+ it("rejects analytics.firebase and analytics.adjust boolean true", () => {
387
+ const raw = {
388
+ packageName: "com.x",
389
+ topsdk: { channel: "GOOGLE", version: "1", groupId: "g", appId: "a", appSecret: "s" },
390
+ sdkModules: {
391
+ login: {},
392
+ payment: {},
393
+ analytics: { appsflyer: false, facebookdata: false, firebase: true, adjust: true },
394
+ },
395
+ };
396
+ expect(tryParseAsMeetSdkRemoteConfig(raw)).toBeNull();
397
+ });
398
+
399
+ it("rejects direct boolean toggles for parameterized plugins", () => {
400
+ const raw = {
401
+ packageName: "com.x",
402
+ topsdk: { channel: "GOOGLE", version: "1", groupId: "g", appId: "a", appSecret: "s" },
403
+ sdkModules: {
404
+ login: { guest: true, email: true, facebook: true, google: true },
405
+ payment: { googleIap: true },
406
+ analytics: { appsflyer: true, facebookdata: true },
407
+ },
408
+ };
409
+ expect(tryParseAsMeetSdkRemoteConfig(raw)).toBeNull();
410
+ });
411
+
412
+ it("does not collect repositories for sdkModules keys absent in remote config", () => {
413
+ const defaults = loadBuiltInMeetSdkDefaultConfig();
414
+ const remote = tryParseAsMeetSdkRemoteConfig({
415
+ packageName: "com.example.game",
416
+ channel: "GOOGLE",
417
+ topsdk: { appId: "1", appSecret: "s" },
418
+ sdkModules: {
419
+ login: { google: { clientId: "g" } },
420
+ payment: {},
421
+ analytics: {},
422
+ },
423
+ });
424
+ expect(remote).not.toBeNull();
425
+ const resolved = applyMeetSdkDefaultConfig(remote!, defaults);
426
+ const repos = collectMeetSdkRemoteRepositories(resolved);
427
+ expect(repos).not.toContain("https://devrepo.kakao.com/nexus/content/groups/public/");
428
+ expect(repos).not.toContain("mavenCentral");
429
+ expect(repos).toContain("https://storage-sdk-gameplus.meetsocial.com/repository/TopSdk/");
430
+ });
431
+
432
+ it("collects plugin repositories from meetsdk-android.json when modules are enabled", () => {
433
+ const defaults = loadBuiltInMeetSdkDefaultConfig();
434
+ const remote = tryParseAsMeetSdkRemoteConfig({
435
+ packageName: "com.example.game",
436
+ channel: "GOOGLE",
437
+ devicePlatform: "android",
438
+ topsdk: { appId: "1", appSecret: "s" },
439
+ sdkModules: {
440
+ login: {
441
+ kakao: { clientId: "k", scheme: "kakao" },
442
+ tiktok: { clientId: "t", secret: "s", redirect: "r" },
443
+ },
444
+ payment: { onestoreIap: {}, huaweiIap: {} },
445
+ analytics: {},
446
+ },
447
+ });
448
+ expect(remote).not.toBeNull();
449
+ const resolved = applyMeetSdkDefaultConfig(remote!, defaults);
450
+ const repos = collectMeetSdkRemoteRepositories(resolved);
451
+ expect(repos).toContain("https://devrepo.kakao.com/nexus/content/groups/public/");
452
+ expect(repos).toContain("https://artifact.bytedance.com/repository/AwemeOpenSDK");
453
+ expect(repos).toContain("https://repo.onestore.co.kr/repository/onestore-sdk-public/");
454
+ expect(repos).toContain("https://developer.huawei.com/repo/");
455
+ });
456
+ });