149 lines
4.5 KiB
JavaScript
149 lines
4.5 KiB
JavaScript
/**
|
|
* Expo Config Plugin: StoreKit Configuration for Sandbox Testing
|
|
*
|
|
* Adds TabataFit.storekit to the Xcode project and configures the scheme
|
|
* to use it for StoreKit testing. This enables purchase testing in the
|
|
* iOS simulator without real Apple Pay charges.
|
|
*/
|
|
|
|
const {
|
|
withXcodeProject,
|
|
withDangerousMod,
|
|
} = require('@expo/config-plugins')
|
|
const fs = require('fs')
|
|
const path = require('path')
|
|
|
|
const STOREKIT_FILENAME = 'TabataFit.storekit'
|
|
|
|
/**
|
|
* Step 1: Copy the .storekit file and add it to the Xcode project (project.pbxproj)
|
|
*/
|
|
function withStoreKitXcodeProject(config) {
|
|
return withXcodeProject(config, (config) => {
|
|
const project = config.modResults
|
|
const projectName = config.modRequest.projectName
|
|
const platformRoot = config.modRequest.platformProjectRoot
|
|
|
|
// Copy .storekit file into the iOS app directory
|
|
const sourceFile = path.resolve(__dirname, '..', 'storekit', STOREKIT_FILENAME)
|
|
const destDir = path.join(platformRoot, projectName)
|
|
const destFile = path.join(destDir, STOREKIT_FILENAME)
|
|
fs.copyFileSync(sourceFile, destFile)
|
|
|
|
// Add file to the Xcode project manually via pbxproj APIs
|
|
// Find the app's PBXGroup
|
|
const mainGroupKey = project.getFirstProject().firstProject.mainGroup
|
|
const mainGroup = project.getPBXGroupByKey(mainGroupKey)
|
|
|
|
// Find the app target group (e.g., "tabatago")
|
|
let appGroupKey = null
|
|
if (mainGroup && mainGroup.children) {
|
|
for (const child of mainGroup.children) {
|
|
if (child.comment === projectName) {
|
|
appGroupKey = child.value
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!appGroupKey) {
|
|
console.warn('[withStoreKitConfig] Could not find app group in Xcode project')
|
|
return config
|
|
}
|
|
|
|
const appGroup = project.getPBXGroupByKey(appGroupKey)
|
|
|
|
// Check if already added
|
|
const alreadyExists = appGroup.children?.some(
|
|
(child) => child.comment === STOREKIT_FILENAME
|
|
)
|
|
|
|
if (!alreadyExists) {
|
|
// Generate a unique UUID for the file reference
|
|
const fileRefUuid = project.generateUuid()
|
|
|
|
// Add PBXFileReference — NOT added to any build phase
|
|
// .storekit files are testing configs, not app resources
|
|
const pbxFileRef = project.hash.project.objects['PBXFileReference']
|
|
pbxFileRef[fileRefUuid] = {
|
|
isa: 'PBXFileReference',
|
|
lastKnownFileType: 'text.json',
|
|
path: STOREKIT_FILENAME,
|
|
sourceTree: '"<group>"',
|
|
}
|
|
pbxFileRef[`${fileRefUuid}_comment`] = STOREKIT_FILENAME
|
|
|
|
// Add to the app group's children (visible in Xcode navigator)
|
|
appGroup.children.push({
|
|
value: fileRefUuid,
|
|
comment: STOREKIT_FILENAME,
|
|
})
|
|
|
|
console.log('[withStoreKitConfig] Added', STOREKIT_FILENAME, 'to Xcode project')
|
|
}
|
|
|
|
return config
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Step 2: Configure the Xcode scheme to use the StoreKit configuration
|
|
*/
|
|
function withStoreKitScheme(config) {
|
|
return withDangerousMod(config, [
|
|
'ios',
|
|
(config) => {
|
|
const projectName = config.modRequest.projectName
|
|
const schemePath = path.join(
|
|
config.modRequest.platformProjectRoot,
|
|
`${projectName}.xcodeproj`,
|
|
'xcshareddata',
|
|
'xcschemes',
|
|
`${projectName}.xcscheme`
|
|
)
|
|
|
|
if (!fs.existsSync(schemePath)) {
|
|
console.warn('[withStoreKitConfig] Scheme not found:', schemePath)
|
|
return config
|
|
}
|
|
|
|
let scheme = fs.readFileSync(schemePath, 'utf8')
|
|
|
|
// Skip if already configured
|
|
if (scheme.includes('storeKitConfigurationFileReference')) {
|
|
console.log('[withStoreKitConfig] StoreKit config already in scheme')
|
|
return config
|
|
}
|
|
|
|
// Insert StoreKitConfigurationFileReference as a child element of LaunchAction
|
|
// The identifier path is relative to the workspace root (ios/ directory)
|
|
const storeKitRef = `
|
|
<StoreKitConfigurationFileReference
|
|
identifier = "${projectName}/${STOREKIT_FILENAME}">
|
|
</StoreKitConfigurationFileReference>`
|
|
|
|
// Insert before the closing </LaunchAction> tag
|
|
scheme = scheme.replace(
|
|
'</LaunchAction>',
|
|
`${storeKitRef}\n </LaunchAction>`
|
|
)
|
|
|
|
fs.writeFileSync(schemePath, scheme, 'utf8')
|
|
console.log('[withStoreKitConfig] Added StoreKit config to scheme')
|
|
|
|
return config
|
|
},
|
|
])
|
|
}
|
|
|
|
/**
|
|
* Main plugin
|
|
*/
|
|
function withStoreKitConfig(config) {
|
|
config = withStoreKitXcodeProject(config)
|
|
config = withStoreKitScheme(config)
|
|
return config
|
|
}
|
|
|
|
module.exports = withStoreKitConfig
|