@leonxin/meetgames 0.1.14 → 0.1.16
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/core/pipeline.js +1 -1
- package/dist/core/pipeline.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/fileManager.js +2 -2
- package/dist/ios/fileManager.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 +123 -34
- 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/core/pipeline.ts +1 -1
- package/src/ios/channelConfig.ts +1 -0
- package/src/ios/fileManager.ts +2 -2
- package/src/ios/infoPlist.ts +0 -7
- package/src/ios/integrate.ts +26 -20
- package/src/ios/pbxprojEditor.ts +135 -35
- package/src/ops/fileStore.ts +7 -6
- package/tests/meetSdkRemoteConfig.test.ts +2 -1
- package/tests/pipeline.ios.test.ts +31 -2
package/src/ios/fileManager.ts
CHANGED
|
@@ -23,7 +23,7 @@ export class TopSdkFileManager {
|
|
|
23
23
|
if (!fs.existsSync(srcPath)) throw new Error(`framework not found: ${srcPath}`);
|
|
24
24
|
const dest = path.join(this.topSdkAbs, base);
|
|
25
25
|
fs.rmSync(dest, { recursive: true, force: true });
|
|
26
|
-
fs.cpSync(srcPath, dest, { recursive: true });
|
|
26
|
+
fs.cpSync(srcPath, dest, { recursive: true, verbatimSymlinks: true });
|
|
27
27
|
return dest;
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -32,7 +32,7 @@ export class TopSdkFileManager {
|
|
|
32
32
|
const base = path.basename(srcPath);
|
|
33
33
|
const dest = path.join(this.topSdkAbs, base);
|
|
34
34
|
fs.rmSync(dest, { recursive: true, force: true });
|
|
35
|
-
fs.cpSync(srcPath, dest, { recursive: true });
|
|
35
|
+
fs.cpSync(srcPath, dest, { recursive: true, verbatimSymlinks: true });
|
|
36
36
|
return dest;
|
|
37
37
|
}
|
|
38
38
|
|
package/src/ios/infoPlist.ts
CHANGED
|
@@ -21,13 +21,6 @@ export function addPlistParam(data: Record<string, unknown>, key: string, value:
|
|
|
21
21
|
data[key] = value;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export function setAppTransportSecurity(data: Record<string, unknown>, open: boolean): void {
|
|
25
|
-
const security =
|
|
26
|
-
(data.NSAppTransportSecurity as Record<string, unknown> | undefined) ?? {};
|
|
27
|
-
security.NSAllowsArbitraryLoads = open;
|
|
28
|
-
data.NSAppTransportSecurity = security;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
24
|
export function addQueriesScheme(data: Record<string, unknown>, scheme: string): void {
|
|
32
25
|
if (!scheme) return;
|
|
33
26
|
const schemes = Array.isArray(data.LSApplicationQueriesSchemes)
|
package/src/ios/integrate.ts
CHANGED
|
@@ -20,7 +20,6 @@ import {
|
|
|
20
20
|
addUrlScheme,
|
|
21
21
|
buildPlistXml,
|
|
22
22
|
parsePlistXml,
|
|
23
|
-
setAppTransportSecurity,
|
|
24
23
|
type PlistDocument,
|
|
25
24
|
} from "./infoPlist.js";
|
|
26
25
|
import {
|
|
@@ -50,6 +49,11 @@ export interface IosIntegrateOptions {
|
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
const IOS_FIREBASE_CONFIG_FILE = "GoogleService-Info.plist";
|
|
52
|
+
const DEFAULT_IOS_BUILD_SETTINGS: Record<string, unknown> = {
|
|
53
|
+
FRAMEWORK_SEARCH_PATHS: ['"$(SRCROOT)/topSDK"', '"$(inherited)"', '"$(PROJECT_DIR)/topSDK"'],
|
|
54
|
+
LIBRARY_SEARCH_PATHS: '"$(SRCROOT)/topSDK"',
|
|
55
|
+
SWIFT_VERSION: "5.0",
|
|
56
|
+
};
|
|
53
57
|
|
|
54
58
|
function logValue(value: unknown): string {
|
|
55
59
|
if (value === undefined) return "<missing>";
|
|
@@ -293,14 +297,27 @@ function ensureTopSdkInstallSwift(
|
|
|
293
297
|
pbx: PbxContext
|
|
294
298
|
): string | null {
|
|
295
299
|
if (hasSwiftSource(pbx.srcRoot)) return null;
|
|
296
|
-
const relFromSrc = path.join(
|
|
300
|
+
const relFromSrc = path.join("topSDK", "TopSDKInstall.swift").split(path.sep).join("/");
|
|
297
301
|
const abs = path.join(pbx.srcRoot, relFromSrc);
|
|
298
302
|
const relFromProject = path.relative(ctx.projectRoot, abs).split(path.sep).join("/");
|
|
299
|
-
store.write(relFromProject, "
|
|
303
|
+
store.write(relFromProject, "");
|
|
300
304
|
addSourceOrResourceFile(pbx, relFromSrc);
|
|
301
305
|
return relFromProject;
|
|
302
306
|
}
|
|
303
307
|
|
|
308
|
+
function applyDefaultIosBuildSettings(pbx: PbxContext, logs: string[]): void {
|
|
309
|
+
for (const [key, value] of Object.entries(DEFAULT_IOS_BUILD_SETTINGS)) {
|
|
310
|
+
const beforeValues = [...new Set(getTargetBuildSettings(pbx).map((settings) => settings[key]))];
|
|
311
|
+
if (beforeValues.length === 0 || beforeValues.some((before) => !valuesEqual(before, value))) {
|
|
312
|
+
setBuildSetting(pbx, key, value);
|
|
313
|
+
}
|
|
314
|
+
for (const before of beforeValues.length ? beforeValues : [undefined]) {
|
|
315
|
+
pushValueChangeLog(logs, `BuildSetting设置${key}`, before, value);
|
|
316
|
+
}
|
|
317
|
+
logs.push(`SUCCESS: BuildSetting设置${key}为${logValue(value)} 完成`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
304
321
|
function appDelegateCodeShouldMoveToSceneDelegate(code: CodeConfig): boolean {
|
|
305
322
|
if (code.type === "header") return false;
|
|
306
323
|
const method = code.method ?? "";
|
|
@@ -406,7 +423,9 @@ function buildTopSdkPluginInfo(
|
|
|
406
423
|
for (const [paramKey, rawValue] of Object.entries(loaded.config.pluginParams ?? {})) {
|
|
407
424
|
params[paramKey] = applyChannelTemplate(String(rawValue), channelConfig);
|
|
408
425
|
}
|
|
409
|
-
|
|
426
|
+
if (Object.keys(params).length > 0) {
|
|
427
|
+
info.params = params;
|
|
428
|
+
}
|
|
410
429
|
}
|
|
411
430
|
if (loaded.config.type === 4) {
|
|
412
431
|
dataPluginsInfo.push(info);
|
|
@@ -558,6 +577,9 @@ export async function runIosIntegrateTopSdk(
|
|
|
558
577
|
|
|
559
578
|
const xcodeprojPath = ctx.ios.xcodeprojPath!;
|
|
560
579
|
const pbx = await loadPbxFromStore(store, ctx.projectRoot, xcodeprojPath, targetName);
|
|
580
|
+
if (perform.includes("buildSettings")) {
|
|
581
|
+
applyDefaultIosBuildSettings(pbx, logs);
|
|
582
|
+
}
|
|
561
583
|
const fm = new TopSdkFileManager(pbx.srcRoot);
|
|
562
584
|
|
|
563
585
|
let plistDocs: PlistDocument[];
|
|
@@ -590,14 +612,6 @@ export async function runIosIntegrateTopSdk(
|
|
|
590
612
|
}
|
|
591
613
|
}
|
|
592
614
|
mergePlistParams(plistDocs, loaded, channelConfig, perform, logs, dirtyPlistDocs);
|
|
593
|
-
if (perform.includes("infoParams")) {
|
|
594
|
-
const doc = plistDocs[0];
|
|
595
|
-
if (doc) {
|
|
596
|
-
const before = cloneValue(doc.data.NSAppTransportSecurity);
|
|
597
|
-
setAppTransportSecurity(doc.data, true);
|
|
598
|
-
if (!valuesEqual(before, doc.data.NSAppTransportSecurity)) dirtyPlistDocs.add(doc);
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
615
|
if (perform.includes("infoParams") && loaded.config.name === "AppleSignin") {
|
|
602
616
|
for (const rel of ensureAppleSignInEntitlement(store, ctx.projectRoot, pbx)) {
|
|
603
617
|
changed.add(rel);
|
|
@@ -609,14 +623,6 @@ export async function runIosIntegrateTopSdk(
|
|
|
609
623
|
for (const loaded of coreConfigs) {
|
|
610
624
|
applyPlugin(loaded, pbx, fm, channelConfig, perform, binaryCopies, dryRun, logs, firebaseDownload.remoteSources);
|
|
611
625
|
mergePlistParams(plistDocs, loaded, channelConfig, perform, logs, dirtyPlistDocs);
|
|
612
|
-
if (perform.includes("infoParams")) {
|
|
613
|
-
const doc = plistDocs[0];
|
|
614
|
-
if (doc) {
|
|
615
|
-
const before = cloneValue(doc.data.NSAppTransportSecurity);
|
|
616
|
-
setAppTransportSecurity(doc.data, true);
|
|
617
|
-
if (!valuesEqual(before, doc.data.NSAppTransportSecurity)) dirtyPlistDocs.add(doc);
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
626
|
if (executeAppDelegate) {
|
|
621
627
|
injectDelegateCodes([loaded], ctx, store, pbx, warnings, changed, logs);
|
|
622
628
|
}
|
package/src/ios/pbxprojEditor.ts
CHANGED
|
@@ -12,6 +12,13 @@ const xcode = require("xcode") as {
|
|
|
12
12
|
project: (pbxprojPath: string) => XcodeProject;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
const EXPECTED_SIGNATURE_BY_XCFRAMEWORK: Record<string, string> = {
|
|
16
|
+
"FBAEMKit.xcframework": '"AppleDeveloperProgram:V9WTTPBFK9:Meta Platforms, Inc."',
|
|
17
|
+
"FBSDKCoreKit.xcframework": '"AppleDeveloperProgram:V9WTTPBFK9:Meta Platforms, Inc."',
|
|
18
|
+
"FBSDKCoreKit_Basics.xcframework": '"AppleDeveloperProgram:V9WTTPBFK9:Meta Platforms, Inc."',
|
|
19
|
+
"FBSDKLoginKit.xcframework": '"AppleDeveloperProgram:V9WTTPBFK9:Meta Platforms, Inc."',
|
|
20
|
+
};
|
|
21
|
+
|
|
15
22
|
export interface PbxContext {
|
|
16
23
|
rel: string;
|
|
17
24
|
proj: XcodeProject;
|
|
@@ -103,7 +110,14 @@ function sanitizePbxBuildSettings(proj: XcodeProject): void {
|
|
|
103
110
|
continue;
|
|
104
111
|
}
|
|
105
112
|
if (Array.isArray(raw)) {
|
|
106
|
-
|
|
113
|
+
const normalized = raw.map((value) => (typeof value === "string" ? quotePbxStringIfNeeded(value) : value));
|
|
114
|
+
const seen = new Set<string>();
|
|
115
|
+
settings[key] = normalized.filter((value) => {
|
|
116
|
+
const marker = typeof value === "string" ? unquotePbxString(value) : JSON.stringify(value);
|
|
117
|
+
if (seen.has(marker)) return false;
|
|
118
|
+
seen.add(marker);
|
|
119
|
+
return true;
|
|
120
|
+
});
|
|
107
121
|
}
|
|
108
122
|
}
|
|
109
123
|
}
|
|
@@ -162,12 +176,15 @@ function ensureResourcesBuildPhase(proj: XcodeProject, targetName: string): void
|
|
|
162
176
|
export function addThirdPartyFramework(ctx: PbxContext, relPathFromSrcRoot: string, embed: boolean): void {
|
|
163
177
|
const file = relPathFromSrcRoot.split(path.sep).join("/");
|
|
164
178
|
const target = targetKey(ctx.proj, ctx.targetName);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
target,
|
|
170
|
-
|
|
179
|
+
const basename = path.basename(file);
|
|
180
|
+
const fileRefUuid = ensureFileRef(ctx, file, frameworkFileType(file));
|
|
181
|
+
addBuildFileToPhase(ctx, ensureFrameworksBuildPhase(ctx, target), fileRefUuid, basename, "Frameworks", ["Weak"]);
|
|
182
|
+
if (embed) {
|
|
183
|
+
addBuildFileToPhase(ctx, ensureCopyFilesBuildPhase(ctx, target), fileRefUuid, basename, "Embed Frameworks", [
|
|
184
|
+
"CodeSignOnCopy",
|
|
185
|
+
"RemoveHeadersOnCopy",
|
|
186
|
+
]);
|
|
187
|
+
}
|
|
171
188
|
}
|
|
172
189
|
|
|
173
190
|
export function addCopyFile(ctx: PbxContext, relPathFromSrcRoot: string): void {
|
|
@@ -202,13 +219,100 @@ function findFileRefUuid(ctx: PbxContext, file: string): string | null {
|
|
|
202
219
|
return null;
|
|
203
220
|
}
|
|
204
221
|
|
|
222
|
+
function frameworkFileType(file: string): string {
|
|
223
|
+
return file.endsWith(".xcframework") ? "wrapper.xcframework" : "wrapper.framework";
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function expectedSignature(file: string): string | undefined {
|
|
227
|
+
return EXPECTED_SIGNATURE_BY_XCFRAMEWORK[path.basename(file)];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function topSdkFileReference(file: string, lastKnownFileType: string): Record<string, unknown> {
|
|
231
|
+
const basename = path.basename(file);
|
|
232
|
+
const ref: Record<string, unknown> = {
|
|
233
|
+
isa: "PBXFileReference",
|
|
234
|
+
};
|
|
235
|
+
const signature = expectedSignature(file);
|
|
236
|
+
if (signature) ref.expectedSignature = signature;
|
|
237
|
+
ref.lastKnownFileType = lastKnownFileType;
|
|
238
|
+
ref.name = basename;
|
|
239
|
+
ref.path = file;
|
|
240
|
+
ref.sourceTree = "SOURCE_ROOT";
|
|
241
|
+
return ref;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function normalizeTopSdkFileReference(ref: Record<string, unknown>, file: string, lastKnownFileType: string): void {
|
|
245
|
+
const normalized = topSdkFileReference(file, lastKnownFileType);
|
|
246
|
+
for (const [key, value] of Object.entries(normalized)) {
|
|
247
|
+
ref[key] = value;
|
|
248
|
+
}
|
|
249
|
+
delete ref.includeInIndex;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function ensureFileRef(ctx: PbxContext, file: string, lastKnownFileType: string): string {
|
|
253
|
+
const basename = path.basename(file);
|
|
254
|
+
const existing = findFileRefUuid(ctx, file);
|
|
255
|
+
const fileRefSection = objectSection(ctx.proj, "PBXFileReference");
|
|
256
|
+
if (existing) {
|
|
257
|
+
const ref = fileRefSection[existing];
|
|
258
|
+
if (ref && typeof ref === "object") {
|
|
259
|
+
normalizeTopSdkFileReference(ref as Record<string, unknown>, file, lastKnownFileType);
|
|
260
|
+
}
|
|
261
|
+
return existing;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const uuid = ctx.proj.generateUuid();
|
|
265
|
+
fileRefSection[uuid] = topSdkFileReference(file, lastKnownFileType);
|
|
266
|
+
fileRefSection[`${uuid}_comment`] = basename;
|
|
267
|
+
return uuid;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function ensureFrameworksBuildPhase(ctx: PbxContext, target: string): Record<string, unknown> {
|
|
271
|
+
try {
|
|
272
|
+
const phase = ctx.proj.pbxFrameworksBuildPhaseObj(target) as Record<string, unknown>;
|
|
273
|
+
phase.files = (phase.files as unknown[]) ?? [];
|
|
274
|
+
return phase;
|
|
275
|
+
} catch {
|
|
276
|
+
ctx.proj.addBuildPhase([], "PBXFrameworksBuildPhase", "Frameworks", target);
|
|
277
|
+
const phase = ctx.proj.pbxFrameworksBuildPhaseObj(target) as Record<string, unknown>;
|
|
278
|
+
phase.files = (phase.files as unknown[]) ?? [];
|
|
279
|
+
return phase;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function addBuildFileToPhase(
|
|
284
|
+
ctx: PbxContext,
|
|
285
|
+
phase: Record<string, unknown>,
|
|
286
|
+
fileRefUuid: string,
|
|
287
|
+
basename: string,
|
|
288
|
+
phaseName: string,
|
|
289
|
+
attributes?: string[]
|
|
290
|
+
): void {
|
|
291
|
+
const files = (phase.files ??= []) as Array<{ value?: string; comment?: string }>;
|
|
292
|
+
if (files.some((file) => file.comment === `${basename} in ${phaseName}`)) return;
|
|
293
|
+
|
|
294
|
+
const buildUuid = ctx.proj.generateUuid();
|
|
295
|
+
const buildFileSection = objectSection(ctx.proj, "PBXBuildFile");
|
|
296
|
+
const buildFile: Record<string, unknown> = {
|
|
297
|
+
isa: "PBXBuildFile",
|
|
298
|
+
fileRef: fileRefUuid,
|
|
299
|
+
fileRef_comment: basename,
|
|
300
|
+
};
|
|
301
|
+
if (attributes?.length) {
|
|
302
|
+
buildFile.settings = { ATTRIBUTES: attributes };
|
|
303
|
+
}
|
|
304
|
+
buildFileSection[buildUuid] = buildFile;
|
|
305
|
+
buildFileSection[`${buildUuid}_comment`] = `${basename} in ${phaseName}`;
|
|
306
|
+
files.push({ value: buildUuid, comment: `${basename} in ${phaseName}` });
|
|
307
|
+
}
|
|
308
|
+
|
|
205
309
|
function ensureCopyFilesBuildPhase(ctx: PbxContext, target: string): Record<string, unknown> {
|
|
206
310
|
const section = objectSection(ctx.proj, "PBXCopyFilesBuildPhase");
|
|
207
311
|
for (const [uuid, raw] of Object.entries(section)) {
|
|
208
312
|
if (uuid.endsWith("_comment") || !raw || typeof raw !== "object") continue;
|
|
209
313
|
const phase = raw as Record<string, unknown>;
|
|
210
314
|
const name = String(phase.name ?? "").replace(/^"|"$/g, "");
|
|
211
|
-
if (name === "
|
|
315
|
+
if (name === "Embed Frameworks" || section[`${uuid}_comment`] === "Embed Frameworks") {
|
|
212
316
|
phase.files = (phase.files as unknown[]) ?? [];
|
|
213
317
|
return phase;
|
|
214
318
|
}
|
|
@@ -221,15 +325,15 @@ function ensureCopyFilesBuildPhase(ctx: PbxContext, target: string): Record<stri
|
|
|
221
325
|
dstPath: '""',
|
|
222
326
|
dstSubfolderSpec: 10,
|
|
223
327
|
files: [],
|
|
224
|
-
name: '"
|
|
328
|
+
name: '"Embed Frameworks"',
|
|
225
329
|
runOnlyForDeploymentPostprocessing: 0,
|
|
226
330
|
};
|
|
227
331
|
section[uuid] = phase;
|
|
228
|
-
section[`${uuid}_comment`] = "
|
|
332
|
+
section[`${uuid}_comment`] = "Embed Frameworks";
|
|
229
333
|
const native = ctx.proj.pbxNativeTargetSection?.()[target] as { buildPhases?: Array<{ value: string; comment: string }> };
|
|
230
334
|
native.buildPhases ??= [];
|
|
231
335
|
if (!native.buildPhases.some((p) => p.value === uuid)) {
|
|
232
|
-
native.buildPhases.push({ value: uuid, comment: "
|
|
336
|
+
native.buildPhases.push({ value: uuid, comment: "Embed Frameworks" });
|
|
233
337
|
}
|
|
234
338
|
return phase;
|
|
235
339
|
}
|
|
@@ -244,15 +348,14 @@ function addCopyFileManually(ctx: PbxContext, target: string, file: string): voi
|
|
|
244
348
|
if (!fileRefUuid) {
|
|
245
349
|
fileRefUuid = ctx.proj.generateUuid();
|
|
246
350
|
const fileRefSection = objectSection(ctx.proj, "PBXFileReference");
|
|
247
|
-
fileRefSection[fileRefUuid] =
|
|
248
|
-
isa: "PBXFileReference",
|
|
249
|
-
name: `"${basename}"`,
|
|
250
|
-
path: `"${file}"`,
|
|
251
|
-
sourceTree: '"<group>"',
|
|
252
|
-
lastKnownFileType: "wrapper.framework",
|
|
253
|
-
includeInIndex: 0,
|
|
254
|
-
};
|
|
351
|
+
fileRefSection[fileRefUuid] = topSdkFileReference(file, "wrapper.framework");
|
|
255
352
|
fileRefSection[`${fileRefUuid}_comment`] = basename;
|
|
353
|
+
} else {
|
|
354
|
+
const fileRefSection = objectSection(ctx.proj, "PBXFileReference");
|
|
355
|
+
const ref = fileRefSection[fileRefUuid];
|
|
356
|
+
if (ref && typeof ref === "object") {
|
|
357
|
+
normalizeTopSdkFileReference(ref as Record<string, unknown>, file, "wrapper.framework");
|
|
358
|
+
}
|
|
256
359
|
}
|
|
257
360
|
|
|
258
361
|
const buildUuid = ctx.proj.generateUuid();
|
|
@@ -289,9 +392,13 @@ export function addSourceOrResourceFile(ctx: PbxContext, relPathFromSrcRoot: str
|
|
|
289
392
|
const target = targetKey(ctx.proj, ctx.targetName);
|
|
290
393
|
if (file.endsWith(".h")) {
|
|
291
394
|
ctx.proj.addHeaderFile(file, { target });
|
|
292
|
-
} else if (file.endsWith(".m") || file.endsWith(".mm") || file.endsWith(".swift")) {
|
|
395
|
+
} else if (file.endsWith(".m") || file.endsWith(".mm") || file.endsWith(".swift") || file.endsWith(".xcdatamodeld")) {
|
|
293
396
|
try {
|
|
294
|
-
|
|
397
|
+
if (file.endsWith(".xcdatamodeld")) {
|
|
398
|
+
addSourceFileManually(ctx, file, "wrapper.xcdatamodel");
|
|
399
|
+
} else {
|
|
400
|
+
ctx.proj.addSourceFile(file, { target });
|
|
401
|
+
}
|
|
295
402
|
} catch (e) {
|
|
296
403
|
if (!String(e instanceof Error ? e.message : e).includes("path")) throw e;
|
|
297
404
|
addSourceFileManually(ctx, file);
|
|
@@ -327,7 +434,7 @@ function sourceFileType(file: string): string {
|
|
|
327
434
|
return "sourcecode.c.objc";
|
|
328
435
|
}
|
|
329
436
|
|
|
330
|
-
function addSourceFileManually(ctx: PbxContext, file: string): void {
|
|
437
|
+
function addSourceFileManually(ctx: PbxContext, file: string, lastKnownFileType?: string): void {
|
|
331
438
|
const basename = path.basename(file);
|
|
332
439
|
ensureSourcesBuildPhase(ctx.proj, ctx.targetName);
|
|
333
440
|
const sources = ctx.proj.pbxSourcesBuildPhaseObj(targetKey(ctx.proj, ctx.targetName));
|
|
@@ -341,10 +448,10 @@ function addSourceFileManually(ctx: PbxContext, file: string): void {
|
|
|
341
448
|
|
|
342
449
|
fileRefSection[fileRefUuid] = {
|
|
343
450
|
isa: "PBXFileReference",
|
|
344
|
-
name:
|
|
345
|
-
path:
|
|
346
|
-
sourceTree:
|
|
347
|
-
lastKnownFileType: sourceFileType(file),
|
|
451
|
+
name: basename,
|
|
452
|
+
path: file,
|
|
453
|
+
sourceTree: "SOURCE_ROOT",
|
|
454
|
+
lastKnownFileType: lastKnownFileType ?? sourceFileType(file),
|
|
348
455
|
};
|
|
349
456
|
fileRefSection[`${fileRefUuid}_comment`] = basename;
|
|
350
457
|
buildFileSection[buildUuid] = {
|
|
@@ -376,14 +483,7 @@ function addResourceFileManually(ctx: PbxContext, file: string, lastKnownFileTyp
|
|
|
376
483
|
const fileRefSection = objectSection(ctx.proj, "PBXFileReference");
|
|
377
484
|
const buildFileSection = objectSection(ctx.proj, "PBXBuildFile");
|
|
378
485
|
|
|
379
|
-
fileRefSection[fileRefUuid] =
|
|
380
|
-
isa: "PBXFileReference",
|
|
381
|
-
name: `"${basename}"`,
|
|
382
|
-
path: `"${file}"`,
|
|
383
|
-
sourceTree: '"<group>"',
|
|
384
|
-
lastKnownFileType: resourceFileType(file, lastKnownFileType),
|
|
385
|
-
includeInIndex: 0,
|
|
386
|
-
};
|
|
486
|
+
fileRefSection[fileRefUuid] = topSdkFileReference(file, resourceFileType(file, lastKnownFileType));
|
|
387
487
|
fileRefSection[`${fileRefUuid}_comment`] = basename;
|
|
388
488
|
buildFileSection[buildUuid] = {
|
|
389
489
|
isa: "PBXBuildFile",
|
|
@@ -394,7 +494,7 @@ function addResourceFileManually(ctx: PbxContext, file: string, lastKnownFileTyp
|
|
|
394
494
|
files.push({ value: buildUuid, comment: `${basename} in Resources` });
|
|
395
495
|
}
|
|
396
496
|
|
|
397
|
-
export function setBuildSetting(ctx: PbxContext, key: string, value:
|
|
497
|
+
export function setBuildSetting(ctx: PbxContext, key: string, value: unknown): void {
|
|
398
498
|
const uuid = targetUuid(ctx.proj, ctx.targetName);
|
|
399
499
|
if (!uuid) return;
|
|
400
500
|
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,38 @@ 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);
|
|
162
|
+
expect(
|
|
163
|
+
fs.readlinkSync(
|
|
164
|
+
path.join(
|
|
165
|
+
tmp,
|
|
166
|
+
"topSDK",
|
|
167
|
+
"FBSDKLoginKit.xcframework",
|
|
168
|
+
"ios-arm64_x86_64-maccatalyst",
|
|
169
|
+
"FBSDKLoginKit.framework",
|
|
170
|
+
"FBSDKLoginKit"
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
).toBe("Versions/Current/FBSDKLoginKit");
|
|
160
174
|
|
|
161
175
|
const pbx = fs.readFileSync(path.join(tmp, "native-sample.xcodeproj", "project.pbxproj"), "utf8");
|
|
162
176
|
expect(pbx).toContain("TOPCore.framework");
|
|
163
177
|
expect(pbx).toContain("TOPGuestSigninPlugin.framework");
|
|
178
|
+
expect(pbx).toContain("TOPIAPPayPlugin.framework in Frameworks");
|
|
179
|
+
expect(pbx).toContain("TOPCoreModel.xcdatamodeld in Sources");
|
|
180
|
+
expect(pbx).not.toContain("TOPCoreModel.xcdatamodeld in Resources");
|
|
181
|
+
expect(pbx).not.toContain("FBSDKLoginKit.xcframework in Resources");
|
|
182
|
+
expect(pbx).toContain(
|
|
183
|
+
'FBSDKLoginKit.xcframework */ = {isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:V9WTTPBFK9:Meta Platforms, Inc."; lastKnownFileType = wrapper.xcframework; name = FBSDKLoginKit.xcframework; path = topSDK/FBSDKLoginKit.xcframework; sourceTree = SOURCE_ROOT; };'
|
|
184
|
+
);
|
|
185
|
+
expect(pbx).toContain("FBSDKCoreKit.xcframework");
|
|
186
|
+
expect(pbx).toContain("FBSDKCoreKit_Basics.xcframework");
|
|
187
|
+
expect(pbx).toContain("FBAEMKit.xcframework");
|
|
188
|
+
expect(pbx).not.toContain('path = "topSDK/FBSDKLoginKit.xcframework"; sourceTree = "<group>";');
|
|
189
|
+
expect(pbx).toContain("LIBRARY_SEARCH_PATHS = \"$(SRCROOT)/topSDK\"");
|
|
190
|
+
expect(pbx).toContain("SWIFT_VERSION = 5.0");
|
|
164
191
|
expect(pbx).toContain('"-ObjC"');
|
|
165
192
|
expect(pbx).toContain("libc++.tbd");
|
|
166
193
|
expect(pbx).not.toMatch(/\n\s+-ObjC,/);
|
|
@@ -177,6 +204,8 @@ describe.skipIf(!hasIosProjectFixture)("pipeline ios fixture", () => {
|
|
|
177
204
|
expect(plist).toContain("<key>APP_ID</key>");
|
|
178
205
|
expect(plist).toContain("mock-ios-native-sample-app-id");
|
|
179
206
|
expect(plist).toContain("GuestSignin");
|
|
207
|
+
expect(plist).toContain("IAPPay");
|
|
208
|
+
expect(plist).not.toContain("NSAppTransportSecurity");
|
|
180
209
|
} finally {
|
|
181
210
|
fs.rmSync(tmp, { recursive: true, force: true });
|
|
182
211
|
}
|
|
@@ -548,7 +577,7 @@ describe.skipIf(!hasIosProjectFixture)("pipeline ios native-sample parity", () =
|
|
|
548
577
|
expect(fs.existsSync(path.join(tmp, "topSDK", "TOPGoogleSigninPlugin.framework"))).toBe(true);
|
|
549
578
|
expect(fs.existsSync(path.join(tmp, "topSDK", "TOPAppleSigninPlugin.framework"))).toBe(true);
|
|
550
579
|
expect(fs.existsSync(path.join(tmp, "topSDK", "TopSDKSource.bundle"))).toBe(true);
|
|
551
|
-
expect(fs.
|
|
580
|
+
expect(fs.readFileSync(path.join(tmp, "topSDK", "TopSDKInstall.swift"), "utf8")).toBe("");
|
|
552
581
|
|
|
553
582
|
const pbx = fs.readFileSync(path.join(tmp, "native-sample.xcodeproj", "project.pbxproj"), "utf8");
|
|
554
583
|
expect(pbx).toContain("TOPUIPlugin.framework");
|