@leonxin/meetgames 0.1.14 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/meetsdk-ios.json +1 -1
- package/dist/config/meetSdkRemoteConfig.d.ts +2 -0
- package/dist/config/meetSdkRemoteConfig.d.ts.map +1 -1
- package/dist/config/meetSdkRemoteConfig.js +14 -1
- package/dist/config/meetSdkRemoteConfig.js.map +1 -1
- package/dist/ios/channelConfig.d.ts.map +1 -1
- package/dist/ios/channelConfig.js +1 -0
- package/dist/ios/channelConfig.js.map +1 -1
- package/dist/ios/infoPlist.d.ts +0 -1
- package/dist/ios/infoPlist.d.ts.map +1 -1
- package/dist/ios/infoPlist.js +0 -5
- package/dist/ios/infoPlist.js.map +1 -1
- package/dist/ios/integrate.d.ts.map +1 -1
- package/dist/ios/integrate.js +26 -22
- package/dist/ios/integrate.js.map +1 -1
- package/dist/ios/pbxprojEditor.d.ts +1 -1
- package/dist/ios/pbxprojEditor.d.ts.map +1 -1
- package/dist/ios/pbxprojEditor.js +88 -15
- package/dist/ios/pbxprojEditor.js.map +1 -1
- package/dist/ops/fileStore.d.ts.map +1 -1
- package/dist/ops/fileStore.js +6 -5
- package/dist/ops/fileStore.js.map +1 -1
- package/package.json +1 -1
- package/src/config/meetSdkRemoteConfig.ts +13 -1
- package/src/ios/channelConfig.ts +1 -0
- package/src/ios/infoPlist.ts +0 -7
- package/src/ios/integrate.ts +26 -20
- package/src/ios/pbxprojEditor.ts +98 -16
- package/src/ops/fileStore.ts +7 -6
- package/tests/meetSdkRemoteConfig.test.ts +2 -1
- package/tests/pipeline.ios.test.ts +12 -2
package/src/ios/pbxprojEditor.ts
CHANGED
|
@@ -103,7 +103,14 @@ function sanitizePbxBuildSettings(proj: XcodeProject): void {
|
|
|
103
103
|
continue;
|
|
104
104
|
}
|
|
105
105
|
if (Array.isArray(raw)) {
|
|
106
|
-
|
|
106
|
+
const normalized = raw.map((value) => (typeof value === "string" ? quotePbxStringIfNeeded(value) : value));
|
|
107
|
+
const seen = new Set<string>();
|
|
108
|
+
settings[key] = normalized.filter((value) => {
|
|
109
|
+
const marker = typeof value === "string" ? unquotePbxString(value) : JSON.stringify(value);
|
|
110
|
+
if (seen.has(marker)) return false;
|
|
111
|
+
seen.add(marker);
|
|
112
|
+
return true;
|
|
113
|
+
});
|
|
107
114
|
}
|
|
108
115
|
}
|
|
109
116
|
}
|
|
@@ -162,12 +169,15 @@ function ensureResourcesBuildPhase(proj: XcodeProject, targetName: string): void
|
|
|
162
169
|
export function addThirdPartyFramework(ctx: PbxContext, relPathFromSrcRoot: string, embed: boolean): void {
|
|
163
170
|
const file = relPathFromSrcRoot.split(path.sep).join("/");
|
|
164
171
|
const target = targetKey(ctx.proj, ctx.targetName);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
target,
|
|
170
|
-
|
|
172
|
+
const basename = path.basename(file);
|
|
173
|
+
const fileRefUuid = ensureFileRef(ctx, file, frameworkFileType(file));
|
|
174
|
+
addBuildFileToPhase(ctx, ensureFrameworksBuildPhase(ctx, target), fileRefUuid, basename, "Frameworks", ["Weak"]);
|
|
175
|
+
if (embed) {
|
|
176
|
+
addBuildFileToPhase(ctx, ensureCopyFilesBuildPhase(ctx, target), fileRefUuid, basename, "Embed Frameworks", [
|
|
177
|
+
"CodeSignOnCopy",
|
|
178
|
+
"RemoveHeadersOnCopy",
|
|
179
|
+
]);
|
|
180
|
+
}
|
|
171
181
|
}
|
|
172
182
|
|
|
173
183
|
export function addCopyFile(ctx: PbxContext, relPathFromSrcRoot: string): void {
|
|
@@ -202,13 +212,81 @@ function findFileRefUuid(ctx: PbxContext, file: string): string | null {
|
|
|
202
212
|
return null;
|
|
203
213
|
}
|
|
204
214
|
|
|
215
|
+
function frameworkFileType(file: string): string {
|
|
216
|
+
return file.endsWith(".xcframework") ? "wrapper.xcframework" : "wrapper.framework";
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function ensureFileRef(ctx: PbxContext, file: string, lastKnownFileType: string): string {
|
|
220
|
+
const basename = path.basename(file);
|
|
221
|
+
const existing = findFileRefUuid(ctx, file);
|
|
222
|
+
const fileRefSection = objectSection(ctx.proj, "PBXFileReference");
|
|
223
|
+
if (existing) {
|
|
224
|
+
const ref = fileRefSection[existing];
|
|
225
|
+
if (ref && typeof ref === "object") {
|
|
226
|
+
(ref as Record<string, unknown>).lastKnownFileType = lastKnownFileType;
|
|
227
|
+
}
|
|
228
|
+
return existing;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const uuid = ctx.proj.generateUuid();
|
|
232
|
+
fileRefSection[uuid] = {
|
|
233
|
+
isa: "PBXFileReference",
|
|
234
|
+
name: `"${basename}"`,
|
|
235
|
+
path: `"${file}"`,
|
|
236
|
+
sourceTree: '"<group>"',
|
|
237
|
+
lastKnownFileType,
|
|
238
|
+
includeInIndex: 0,
|
|
239
|
+
};
|
|
240
|
+
fileRefSection[`${uuid}_comment`] = basename;
|
|
241
|
+
return uuid;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function ensureFrameworksBuildPhase(ctx: PbxContext, target: string): Record<string, unknown> {
|
|
245
|
+
try {
|
|
246
|
+
const phase = ctx.proj.pbxFrameworksBuildPhaseObj(target) as Record<string, unknown>;
|
|
247
|
+
phase.files = (phase.files as unknown[]) ?? [];
|
|
248
|
+
return phase;
|
|
249
|
+
} catch {
|
|
250
|
+
ctx.proj.addBuildPhase([], "PBXFrameworksBuildPhase", "Frameworks", target);
|
|
251
|
+
const phase = ctx.proj.pbxFrameworksBuildPhaseObj(target) as Record<string, unknown>;
|
|
252
|
+
phase.files = (phase.files as unknown[]) ?? [];
|
|
253
|
+
return phase;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function addBuildFileToPhase(
|
|
258
|
+
ctx: PbxContext,
|
|
259
|
+
phase: Record<string, unknown>,
|
|
260
|
+
fileRefUuid: string,
|
|
261
|
+
basename: string,
|
|
262
|
+
phaseName: string,
|
|
263
|
+
attributes?: string[]
|
|
264
|
+
): void {
|
|
265
|
+
const files = (phase.files ??= []) as Array<{ value?: string; comment?: string }>;
|
|
266
|
+
if (files.some((file) => file.comment === `${basename} in ${phaseName}`)) return;
|
|
267
|
+
|
|
268
|
+
const buildUuid = ctx.proj.generateUuid();
|
|
269
|
+
const buildFileSection = objectSection(ctx.proj, "PBXBuildFile");
|
|
270
|
+
const buildFile: Record<string, unknown> = {
|
|
271
|
+
isa: "PBXBuildFile",
|
|
272
|
+
fileRef: fileRefUuid,
|
|
273
|
+
fileRef_comment: basename,
|
|
274
|
+
};
|
|
275
|
+
if (attributes?.length) {
|
|
276
|
+
buildFile.settings = { ATTRIBUTES: attributes };
|
|
277
|
+
}
|
|
278
|
+
buildFileSection[buildUuid] = buildFile;
|
|
279
|
+
buildFileSection[`${buildUuid}_comment`] = `${basename} in ${phaseName}`;
|
|
280
|
+
files.push({ value: buildUuid, comment: `${basename} in ${phaseName}` });
|
|
281
|
+
}
|
|
282
|
+
|
|
205
283
|
function ensureCopyFilesBuildPhase(ctx: PbxContext, target: string): Record<string, unknown> {
|
|
206
284
|
const section = objectSection(ctx.proj, "PBXCopyFilesBuildPhase");
|
|
207
285
|
for (const [uuid, raw] of Object.entries(section)) {
|
|
208
286
|
if (uuid.endsWith("_comment") || !raw || typeof raw !== "object") continue;
|
|
209
287
|
const phase = raw as Record<string, unknown>;
|
|
210
288
|
const name = String(phase.name ?? "").replace(/^"|"$/g, "");
|
|
211
|
-
if (name === "
|
|
289
|
+
if (name === "Embed Frameworks" || section[`${uuid}_comment`] === "Embed Frameworks") {
|
|
212
290
|
phase.files = (phase.files as unknown[]) ?? [];
|
|
213
291
|
return phase;
|
|
214
292
|
}
|
|
@@ -221,15 +299,15 @@ function ensureCopyFilesBuildPhase(ctx: PbxContext, target: string): Record<stri
|
|
|
221
299
|
dstPath: '""',
|
|
222
300
|
dstSubfolderSpec: 10,
|
|
223
301
|
files: [],
|
|
224
|
-
name: '"
|
|
302
|
+
name: '"Embed Frameworks"',
|
|
225
303
|
runOnlyForDeploymentPostprocessing: 0,
|
|
226
304
|
};
|
|
227
305
|
section[uuid] = phase;
|
|
228
|
-
section[`${uuid}_comment`] = "
|
|
306
|
+
section[`${uuid}_comment`] = "Embed Frameworks";
|
|
229
307
|
const native = ctx.proj.pbxNativeTargetSection?.()[target] as { buildPhases?: Array<{ value: string; comment: string }> };
|
|
230
308
|
native.buildPhases ??= [];
|
|
231
309
|
if (!native.buildPhases.some((p) => p.value === uuid)) {
|
|
232
|
-
native.buildPhases.push({ value: uuid, comment: "
|
|
310
|
+
native.buildPhases.push({ value: uuid, comment: "Embed Frameworks" });
|
|
233
311
|
}
|
|
234
312
|
return phase;
|
|
235
313
|
}
|
|
@@ -289,9 +367,13 @@ export function addSourceOrResourceFile(ctx: PbxContext, relPathFromSrcRoot: str
|
|
|
289
367
|
const target = targetKey(ctx.proj, ctx.targetName);
|
|
290
368
|
if (file.endsWith(".h")) {
|
|
291
369
|
ctx.proj.addHeaderFile(file, { target });
|
|
292
|
-
} else if (file.endsWith(".m") || file.endsWith(".mm") || file.endsWith(".swift")) {
|
|
370
|
+
} else if (file.endsWith(".m") || file.endsWith(".mm") || file.endsWith(".swift") || file.endsWith(".xcdatamodeld")) {
|
|
293
371
|
try {
|
|
294
|
-
|
|
372
|
+
if (file.endsWith(".xcdatamodeld")) {
|
|
373
|
+
addSourceFileManually(ctx, file, "wrapper.xcdatamodel");
|
|
374
|
+
} else {
|
|
375
|
+
ctx.proj.addSourceFile(file, { target });
|
|
376
|
+
}
|
|
295
377
|
} catch (e) {
|
|
296
378
|
if (!String(e instanceof Error ? e.message : e).includes("path")) throw e;
|
|
297
379
|
addSourceFileManually(ctx, file);
|
|
@@ -327,7 +409,7 @@ function sourceFileType(file: string): string {
|
|
|
327
409
|
return "sourcecode.c.objc";
|
|
328
410
|
}
|
|
329
411
|
|
|
330
|
-
function addSourceFileManually(ctx: PbxContext, file: string): void {
|
|
412
|
+
function addSourceFileManually(ctx: PbxContext, file: string, lastKnownFileType?: string): void {
|
|
331
413
|
const basename = path.basename(file);
|
|
332
414
|
ensureSourcesBuildPhase(ctx.proj, ctx.targetName);
|
|
333
415
|
const sources = ctx.proj.pbxSourcesBuildPhaseObj(targetKey(ctx.proj, ctx.targetName));
|
|
@@ -344,7 +426,7 @@ function addSourceFileManually(ctx: PbxContext, file: string): void {
|
|
|
344
426
|
name: `"${basename}"`,
|
|
345
427
|
path: `"${file}"`,
|
|
346
428
|
sourceTree: '"<group>"',
|
|
347
|
-
lastKnownFileType: sourceFileType(file),
|
|
429
|
+
lastKnownFileType: lastKnownFileType ?? sourceFileType(file),
|
|
348
430
|
};
|
|
349
431
|
fileRefSection[`${fileRefUuid}_comment`] = basename;
|
|
350
432
|
buildFileSection[buildUuid] = {
|
|
@@ -394,7 +476,7 @@ function addResourceFileManually(ctx: PbxContext, file: string, lastKnownFileTyp
|
|
|
394
476
|
files.push({ value: buildUuid, comment: `${basename} in Resources` });
|
|
395
477
|
}
|
|
396
478
|
|
|
397
|
-
export function setBuildSetting(ctx: PbxContext, key: string, value:
|
|
479
|
+
export function setBuildSetting(ctx: PbxContext, key: string, value: unknown): void {
|
|
398
480
|
const uuid = targetUuid(ctx.proj, ctx.targetName);
|
|
399
481
|
if (!uuid) return;
|
|
400
482
|
const native = ctx.proj.pbxNativeTargetSection?.()[uuid] as { buildConfigurationList?: string };
|
package/src/ops/fileStore.ts
CHANGED
|
@@ -4,7 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
/** Tracks text file originals and pending content for dry-run / apply */
|
|
5
5
|
export class TextFileStore {
|
|
6
6
|
private readonly projectRoot: string;
|
|
7
|
-
private readonly map = new Map<string, { original: string; current: string }>();
|
|
7
|
+
private readonly map = new Map<string, { original: string; current: string; existed: boolean }>();
|
|
8
8
|
|
|
9
9
|
constructor(projectRoot: string) {
|
|
10
10
|
this.projectRoot = projectRoot;
|
|
@@ -20,7 +20,7 @@ export class TextFileStore {
|
|
|
20
20
|
const abs = path.join(this.projectRoot, rel);
|
|
21
21
|
if (!fs.existsSync(abs)) return "";
|
|
22
22
|
const content = fs.readFileSync(abs, "utf8");
|
|
23
|
-
this.map.set(rel, { original: content, current: content });
|
|
23
|
+
this.map.set(rel, { original: content, current: content, existed: true });
|
|
24
24
|
return content;
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -32,22 +32,23 @@ export class TextFileStore {
|
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
34
|
let original = "";
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const existed = fs.existsSync(abs);
|
|
36
|
+
if (existed) original = fs.readFileSync(abs, "utf8");
|
|
37
|
+
this.map.set(rel, { original, current: content, existed });
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
/** Files where current !== original */
|
|
40
41
|
changedEntries(): Array<{ rel: string; original: string; current: string }> {
|
|
41
42
|
const out: Array<{ rel: string; original: string; current: string }> = [];
|
|
42
43
|
for (const [rel, v] of this.map) {
|
|
43
|
-
if (v.current !== v.original) out.push({ rel, original: v.original, current: v.current });
|
|
44
|
+
if (!v.existed || v.current !== v.original) out.push({ rel, original: v.original, current: v.current });
|
|
44
45
|
}
|
|
45
46
|
return out;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
flushToDisk(): void {
|
|
49
50
|
for (const [rel, v] of this.map) {
|
|
50
|
-
if (v.current === v.original) continue;
|
|
51
|
+
if (v.existed && v.current === v.original) continue;
|
|
51
52
|
const abs = path.join(this.projectRoot, rel);
|
|
52
53
|
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
53
54
|
fs.writeFileSync(abs, v.current, "utf8");
|
|
@@ -53,7 +53,7 @@ describe("meetSdkRemoteConfig", () => {
|
|
|
53
53
|
naver: { clientId: "naver-client", secret: "naver-secret", name: "Naver", scheme: "naver-scheme" },
|
|
54
54
|
apple: {},
|
|
55
55
|
},
|
|
56
|
-
payment: {},
|
|
56
|
+
payment: { appleIap: {} },
|
|
57
57
|
analytics: {
|
|
58
58
|
appsflyer: { devKey: "af-key", appleAppId: "1234567890" },
|
|
59
59
|
firebase: { firebaseUrl: "https://cdn.example/GoogleService-Info.plist", firebaseName: "GoogleService-Info.plist" },
|
|
@@ -82,6 +82,7 @@ describe("meetSdkRemoteConfig", () => {
|
|
|
82
82
|
devKey: "af-key",
|
|
83
83
|
appleAppId: "1234567890",
|
|
84
84
|
});
|
|
85
|
+
expect(parsed!.sdkModules.payment.appleIap).toMatchObject({});
|
|
85
86
|
});
|
|
86
87
|
|
|
87
88
|
it("does not treat legacy remote field names as valid config", () => {
|
|
@@ -50,7 +50,7 @@ function writeNativeSampleRemoteConfig(projectRoot: string): void {
|
|
|
50
50
|
apple: {},
|
|
51
51
|
},
|
|
52
52
|
payment: {
|
|
53
|
-
|
|
53
|
+
appleIap: {},
|
|
54
54
|
},
|
|
55
55
|
analytics: {
|
|
56
56
|
appsflyer: {
|
|
@@ -156,11 +156,19 @@ describe.skipIf(!hasIosProjectFixture)("pipeline ios fixture", () => {
|
|
|
156
156
|
expect(fs.existsSync(path.join(tmp, "topSDK", "TOPCore.framework"))).toBe(true);
|
|
157
157
|
expect(fs.existsSync(path.join(tmp, "topSDK", "TOPSDK.framework"))).toBe(true);
|
|
158
158
|
expect(fs.existsSync(path.join(tmp, "topSDK", "TOPGuestSigninPlugin.framework"))).toBe(true);
|
|
159
|
+
expect(fs.existsSync(path.join(tmp, "topSDK", "TOPIAPPayPlugin.framework"))).toBe(true);
|
|
160
|
+
expect(fs.readFileSync(path.join(tmp, "topSDK", "TopSDKInstall.swift"), "utf8")).toBe("");
|
|
159
161
|
expect(fs.existsSync(path.join(tmp, "topSDK", "TopSDKSource.bundle"))).toBe(true);
|
|
160
162
|
|
|
161
163
|
const pbx = fs.readFileSync(path.join(tmp, "native-sample.xcodeproj", "project.pbxproj"), "utf8");
|
|
162
164
|
expect(pbx).toContain("TOPCore.framework");
|
|
163
165
|
expect(pbx).toContain("TOPGuestSigninPlugin.framework");
|
|
166
|
+
expect(pbx).toContain("TOPIAPPayPlugin.framework in Frameworks");
|
|
167
|
+
expect(pbx).toContain("TOPCoreModel.xcdatamodeld in Sources");
|
|
168
|
+
expect(pbx).not.toContain("TOPCoreModel.xcdatamodeld in Resources");
|
|
169
|
+
expect(pbx).not.toContain("FBSDKLoginKit.xcframework in Resources");
|
|
170
|
+
expect(pbx).toContain("LIBRARY_SEARCH_PATHS = \"$(SRCROOT)/topSDK\"");
|
|
171
|
+
expect(pbx).toContain("SWIFT_VERSION = 5.0");
|
|
164
172
|
expect(pbx).toContain('"-ObjC"');
|
|
165
173
|
expect(pbx).toContain("libc++.tbd");
|
|
166
174
|
expect(pbx).not.toMatch(/\n\s+-ObjC,/);
|
|
@@ -177,6 +185,8 @@ describe.skipIf(!hasIosProjectFixture)("pipeline ios fixture", () => {
|
|
|
177
185
|
expect(plist).toContain("<key>APP_ID</key>");
|
|
178
186
|
expect(plist).toContain("mock-ios-native-sample-app-id");
|
|
179
187
|
expect(plist).toContain("GuestSignin");
|
|
188
|
+
expect(plist).toContain("IAPPay");
|
|
189
|
+
expect(plist).not.toContain("NSAppTransportSecurity");
|
|
180
190
|
} finally {
|
|
181
191
|
fs.rmSync(tmp, { recursive: true, force: true });
|
|
182
192
|
}
|
|
@@ -548,7 +558,7 @@ describe.skipIf(!hasIosProjectFixture)("pipeline ios native-sample parity", () =
|
|
|
548
558
|
expect(fs.existsSync(path.join(tmp, "topSDK", "TOPGoogleSigninPlugin.framework"))).toBe(true);
|
|
549
559
|
expect(fs.existsSync(path.join(tmp, "topSDK", "TOPAppleSigninPlugin.framework"))).toBe(true);
|
|
550
560
|
expect(fs.existsSync(path.join(tmp, "topSDK", "TopSDKSource.bundle"))).toBe(true);
|
|
551
|
-
expect(fs.
|
|
561
|
+
expect(fs.readFileSync(path.join(tmp, "topSDK", "TopSDKInstall.swift"), "utf8")).toBe("");
|
|
552
562
|
|
|
553
563
|
const pbx = fs.readFileSync(path.join(tmp, "native-sample.xcodeproj", "project.pbxproj"), "utf8");
|
|
554
564
|
expect(pbx).toContain("TOPUIPlugin.framework");
|