@leonxin/meetgames 0.1.8 → 0.1.12

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