Skip to content

Commit c826956

Browse files
Copilotfarfromrefug
andcommitted
Implement SPMPackages override: allow app to override plugin packages
Co-authored-by: farfromrefug <655344+farfromrefug@users.noreply.github.com>
1 parent a964a6d commit c826956

2 files changed

Lines changed: 186 additions & 1 deletion

File tree

lib/services/ios/spm-service.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,16 @@ export class SPMService implements ISPMService {
4242

4343
if (pluginSpmPackages?.length) {
4444
// include swift packages from plugin configs
45-
spmPackages.push(...pluginSpmPackages);
45+
// but allow app packages to override plugin packages with the same name
46+
const appPackageNames = new Set(spmPackages.map(pkg => pkg.name));
47+
48+
for (const pluginPkg of pluginSpmPackages) {
49+
if (appPackageNames.has(pluginPkg.name)) {
50+
this.$logger.trace(`SPM: app package overrides plugin package: ${pluginPkg.name}`);
51+
} else {
52+
spmPackages.push(pluginPkg);
53+
}
54+
}
4655
}
4756

4857
if (!spmPackages.length) {

test/spm-service.ts

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import { assert } from "chai";
2+
3+
describe("SPM Service - Package Override Logic", () => {
4+
describe("merging app and plugin SPM packages", () => {
5+
it("should allow app packages to override plugin packages with the same name", () => {
6+
// This test validates the merge logic without requiring MobileProject
7+
const appPackages = [
8+
{
9+
name: "FirebaseCore",
10+
repositoryURL: "https://github.com/firebase/firebase-ios-sdk",
11+
version: "10.0.0",
12+
libs: ["FirebaseCore"],
13+
},
14+
];
15+
16+
const pluginPackages = [
17+
{
18+
name: "FirebaseCore",
19+
repositoryURL: "https://github.com/firebase/firebase-ios-sdk",
20+
version: "9.0.0",
21+
libs: ["FirebaseCore"],
22+
},
23+
{
24+
name: "Alamofire",
25+
repositoryURL: "https://github.com/Alamofire/Alamofire",
26+
version: "5.0.0",
27+
libs: ["Alamofire"],
28+
},
29+
];
30+
31+
// Simulate the merge logic from spm-service.ts
32+
const spmPackages = [...appPackages];
33+
const appPackageNames = new Set(spmPackages.map(pkg => pkg.name));
34+
35+
for (const pluginPkg of pluginPackages) {
36+
if (!appPackageNames.has(pluginPkg.name)) {
37+
spmPackages.push(pluginPkg);
38+
}
39+
}
40+
41+
// Verify the result
42+
assert.equal(spmPackages.length, 2, "Should have 2 packages total");
43+
44+
const firebasePackage = spmPackages.find((pkg) => pkg.name === "FirebaseCore");
45+
assert.isDefined(firebasePackage, "Should include FirebaseCore package");
46+
assert.equal(
47+
firebasePackage.version,
48+
"10.0.0",
49+
"Should use app's FirebaseCore version (10.0.0), not plugin's (9.0.0)",
50+
);
51+
52+
const alamofirePackage = spmPackages.find((pkg) => pkg.name === "Alamofire");
53+
assert.isDefined(alamofirePackage, "Should include Alamofire package from plugin");
54+
assert.equal(alamofirePackage.version, "5.0.0", "Should use plugin's Alamofire version");
55+
});
56+
57+
it("should include all plugin packages when no app packages exist", () => {
58+
const appPackages: any[] = [];
59+
60+
const pluginPackages = [
61+
{
62+
name: "FirebaseCore",
63+
repositoryURL: "https://github.com/firebase/firebase-ios-sdk",
64+
version: "9.0.0",
65+
libs: ["FirebaseCore"],
66+
},
67+
{
68+
name: "Alamofire",
69+
repositoryURL: "https://github.com/Alamofire/Alamofire",
70+
version: "5.0.0",
71+
libs: ["Alamofire"],
72+
},
73+
];
74+
75+
// Simulate the merge logic
76+
const spmPackages = [...appPackages];
77+
const appPackageNames = new Set(spmPackages.map(pkg => pkg.name));
78+
79+
for (const pluginPkg of pluginPackages) {
80+
if (!appPackageNames.has(pluginPkg.name)) {
81+
spmPackages.push(pluginPkg);
82+
}
83+
}
84+
85+
// Verify the result
86+
assert.equal(spmPackages.length, 2, "Should include both plugin packages");
87+
88+
const packageNames = spmPackages.map((pkg) => pkg.name);
89+
assert.include(packageNames, "FirebaseCore", "Should include FirebaseCore");
90+
assert.include(packageNames, "Alamofire", "Should include Alamofire");
91+
});
92+
93+
it("should handle local packages override correctly", () => {
94+
const appPackages = [
95+
{
96+
name: "LocalSDK",
97+
path: "./custom-sdk",
98+
libs: ["LocalSDK"],
99+
},
100+
];
101+
102+
const pluginPackages = [
103+
{
104+
name: "LocalSDK",
105+
path: "./plugin-sdk",
106+
libs: ["LocalSDK"],
107+
},
108+
];
109+
110+
// Simulate the merge logic
111+
const spmPackages = [...appPackages];
112+
const appPackageNames = new Set(spmPackages.map(pkg => pkg.name));
113+
114+
for (const pluginPkg of pluginPackages) {
115+
if (!appPackageNames.has(pluginPkg.name)) {
116+
spmPackages.push(pluginPkg);
117+
}
118+
}
119+
120+
// Verify the result
121+
assert.equal(spmPackages.length, 1, "Should have exactly 1 package");
122+
123+
const localPackage = spmPackages.find((pkg) => pkg.name === "LocalSDK");
124+
assert.isDefined(localPackage, "Should include LocalSDK package");
125+
assert.equal(
126+
(localPackage as any).path,
127+
"./custom-sdk",
128+
"Should use app's LocalSDK path, not plugin's",
129+
);
130+
});
131+
132+
it("should keep all packages when there are no name conflicts", () => {
133+
const appPackages = [
134+
{
135+
name: "FirebaseCore",
136+
repositoryURL: "https://github.com/firebase/firebase-ios-sdk",
137+
version: "10.0.0",
138+
libs: ["FirebaseCore"],
139+
},
140+
];
141+
142+
const pluginPackages = [
143+
{
144+
name: "Alamofire",
145+
repositoryURL: "https://github.com/Alamofire/Alamofire",
146+
version: "5.0.0",
147+
libs: ["Alamofire"],
148+
},
149+
{
150+
name: "Kingfisher",
151+
repositoryURL: "https://github.com/onevcat/Kingfisher",
152+
version: "7.0.0",
153+
libs: ["Kingfisher"],
154+
},
155+
];
156+
157+
// Simulate the merge logic
158+
const spmPackages = [...appPackages];
159+
const appPackageNames = new Set(spmPackages.map(pkg => pkg.name));
160+
161+
for (const pluginPkg of pluginPackages) {
162+
if (!appPackageNames.has(pluginPkg.name)) {
163+
spmPackages.push(pluginPkg);
164+
}
165+
}
166+
167+
// Verify the result
168+
assert.equal(spmPackages.length, 3, "Should have all 3 packages");
169+
170+
const packageNames = spmPackages.map((pkg) => pkg.name);
171+
assert.include(packageNames, "FirebaseCore");
172+
assert.include(packageNames, "Alamofire");
173+
assert.include(packageNames, "Kingfisher");
174+
});
175+
});
176+
});

0 commit comments

Comments
 (0)