Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions cli/src/build/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1086,14 +1086,14 @@ export async function zipDirectory(projectDir: string, outputPath: string, platf
const original = entry.getData().toString('utf-8')
let rewritten = original.replace(pnpmPathPattern, 'node_modules/')

// pod install with pnpm resolves symlinks, producing deep relative paths
// like ../../../../../../ios/App/Pods/ (6 levels) instead of ../../../ios/App/Pods/ (3 levels).
// Collapse any excessive ../ before the platform directory back to 3 levels
// (node_modules/@scope/pkg → 3 levels up to project root).
// pnpm can leave deep relative paths in iOS files like Package.swift and Pods output.
// Collapse any excessive ../ before project-root ios/ or node_modules/ paths back to
// the current zip entry's actual depth.
if (platform === 'ios') {
const rootRelativePrefix = '../'.repeat(entry.entryName.split('/').length - 1)
rewritten = rewritten.replace(
/(?:\.\.\/){4,}(ios\/)/g,
'../../../$1',
/(?:\.\.\/){4,}(ios\/|node_modules\/)/g,
(_match, rootPath: string) => `${rootRelativePrefix}${rootPath}`,
)
}

Expand Down
25 changes: 25 additions & 0 deletions cli/test/test-build-zip-filter.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,10 @@ await t('generated build zip supports nested Capacitor Podfile paths in monorepo
join(testRoot, 'apps/native/ios/App/Podfile'),
"platform :ios, '14.0'\npod 'CapacitorApp', :path => '../../../node_modules/@capacitor/app'\n",
)
writeFile(
join(testRoot, 'apps/native/ios/App/CapApp-SPM/Package.swift'),
'let package = Package(name: "CapApp-SPM", dependencies: [.package(name: "CapacitorApp", path: "../../../../../node_modules/.pnpm/@capacitor+app@6.0.0_@capacitor+core@6.0.0/node_modules/@capacitor/app")])\n',
)

writeFile(
join(testRoot, 'apps/native/ios/App/Podfile.lock'),
Expand All @@ -216,6 +220,10 @@ await t('generated build zip supports nested Capacitor Podfile paths in monorepo
join(testRoot, 'node_modules', '@capacitor', 'app', 'CapacitorApp.podspec'),
"Pod::Spec.new do |s|\n s.name = 'CapacitorApp'\nend",
)
writeFile(
join(testRoot, 'node_modules', '@capacitor', 'app', 'Package.swift'),
'let package = Package(name: "CapacitorApp")\n',
)

await zipDirectory(testRoot, zipPath, 'ios', {
ios: {
Expand All @@ -229,6 +237,10 @@ await t('generated build zip supports nested Capacitor Podfile paths in monorepo
assert.ok(entries.includes('apps/native/ios/App/Podfile'), 'native platform podfile not included')
assert.ok(entries.includes('node_modules/@capacitor/app/package.json'), 'missing plugin package.json in zip')
assert.ok(entries.includes('node_modules/@capacitor/app/CapacitorApp.podspec'), 'missing plugin podspec in zip')
assert.equal(
zip.readAsText('apps/native/ios/App/CapApp-SPM/Package.swift'),
'let package = Package(name: "CapApp-SPM", dependencies: [.package(name: "CapacitorApp", path: "../../../../../node_modules/@capacitor/app")])\n',
)
assert.ok(!entries.includes('apps/native/ios/Podfile.lock'), 'unexpected root lockfile was included')
}
finally {
Expand Down Expand Up @@ -450,11 +462,19 @@ await t('generated build zip can pull native pnpm workspace packages from an exp
join(projectRoot, 'ios', 'App', 'Podfile'),
"platform :ios, '14.0'\npod 'CapacitorCommunityKeepAwake', :path => '../../node_modules/@capacitor-community/keep-awake'\n",
)
writeFile(
join(projectRoot, 'ios', 'App', 'CapApp-SPM', 'Package.swift'),
'let package = Package(name: "CapApp-SPM", dependencies: [.package(name: "CapacitorCommunityKeepAwake", path: "../../../../../node_modules/.pnpm/@capacitor-community+keep-awake@8.0.0_@capacitor+core@8.2.0/node_modules/@capacitor-community/keep-awake")])\n',
)

writeFile(
join(keepAwakePath, 'package.json'),
JSON.stringify({ name: '@capacitor-community/keep-awake', version: '8.0.0' }, null, 2),
)
writeFile(
join(keepAwakePath, 'Package.swift'),
'let package = Package(name: "CapacitorCommunityKeepAwake")\n',
)
writeFile(
join(keepAwakePath, 'KeepAwake.podspec'),
"Pod::Spec.new do |s|\n s.name = 'KeepAwake'\nend",
Expand All @@ -476,9 +496,14 @@ await t('generated build zip can pull native pnpm workspace packages from an exp
const entries = zip.getEntries().map(entry => entry.entryName).sort()

assert.ok(entries.includes('node_modules/@capacitor-community/keep-awake/package.json'), 'missing workspace plugin package.json in zip')
assert.ok(entries.includes('node_modules/@capacitor-community/keep-awake/Package.swift'), 'missing workspace plugin Package.swift in zip')
assert.ok(entries.includes('node_modules/@capacitor-community/keep-awake/KeepAwake.podspec'), 'missing workspace plugin podspec in zip')
assert.ok(entries.includes('node_modules/@capacitor-community/keep-awake/ios/KeepAwakePlugin.swift'), 'missing workspace plugin ios code in zip')
assert.ok(entries.includes('ios/App/Podfile'), 'native platform folder not included')
assert.equal(
zip.readAsText('ios/App/CapApp-SPM/Package.swift'),
'let package = Package(name: "CapApp-SPM", dependencies: [.package(name: "CapacitorCommunityKeepAwake", path: "../../../node_modules/@capacitor-community/keep-awake")])\n',
)
}
finally {
rmSync(testRoot, { recursive: true, force: true })
Expand Down
Loading