UNPKG

expo-finance-kit

Version:

Native Expo module for Apple FinanceKit - Access financial data from Apple Card and other accounts

194 lines (180 loc) 8.09 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.withBackgroundDeliveryExtension = void 0; const config_plugins_1 = require("@expo/config-plugins"); const plist_1 = __importDefault(require("@expo/plist")); const fs = __importStar(require("fs")); const path = __importStar(require("path")); // FinanceKit background delivery extension type const FINANCE_KIT_EXTENSION_IDENTIFIER = 'com.apple.financekit.background-delivery'; /** * Creates the extension target Info.plist content */ function getExtensionInfoPlist(extensionName) { return plist_1.default.build({ CFBundleDevelopmentRegion: '$(DEVELOPMENT_LANGUAGE)', CFBundleDisplayName: extensionName, CFBundleExecutable: '$(EXECUTABLE_NAME)', CFBundleIdentifier: '$(PRODUCT_BUNDLE_IDENTIFIER)', CFBundleInfoDictionaryVersion: '6.0', CFBundleName: '$(PRODUCT_NAME)', CFBundlePackageType: '$(PRODUCT_BUNDLE_PACKAGE_TYPE)', CFBundleShortVersionString: '$(MARKETING_VERSION)', CFBundleVersion: '$(CURRENT_PROJECT_VERSION)', NSExtension: { NSExtensionPointIdentifier: FINANCE_KIT_EXTENSION_IDENTIFIER, NSExtensionPrincipalClass: '$(PRODUCT_MODULE_NAME).BackgroundDeliveryExtension', }, NSFinancialDataUsageDescription: 'This extension receives notifications when financial data changes to keep your app up to date.', }); } /** * Creates the extension entitlements content */ function getExtensionEntitlements(appGroupIdentifier) { return plist_1.default.build({ 'com.apple.security.application-groups': [appGroupIdentifier], 'com.apple.developer.financekit': true, }); } /** * Generates the Swift source code for the extension */ function generateSwiftContent(appGroupIdentifier, bundleIdentifier) { return `import FinanceKit import BackgroundTasks import os.log @available(iOS 17.4, *) class BackgroundDeliveryExtension: NSObject { private let logger: Logger override init() { // Use dynamic bundle identifier for logger let bundleId = Bundle.main.bundleIdentifier ?? "${bundleIdentifier || 'com.expo.financekit'}" self.logger = Logger(subsystem: bundleId, category: "BackgroundDelivery") super.init() logger.info("BackgroundDeliveryExtension initialized") } } @available(iOS 17.4, *) extension BackgroundDeliveryExtension: FinanceStoreDataExtension { func financeStoreDidChange() async { logger.info("Received finance store change notification") // Store sync timestamp if let appGroupURL = FileManager.default.containerURL( forSecurityApplicationGroupIdentifier: "${appGroupIdentifier}" ) { let syncData = ["timestamp": Date().timeIntervalSince1970] let fileURL = appGroupURL.appendingPathComponent("last_sync.json") if let jsonData = try? JSONSerialization.data(withJSONObject: syncData) { try? jsonData.write(to: fileURL) } } // Notify main app let mainBundleId = Bundle.main.bundleIdentifier?.replacingOccurrences(of: ".finance-background", with: "") ?? "${bundleIdentifier || 'com.expo.financekit'}" let notificationCenter = CFNotificationCenterGetDarwinNotifyCenter() let notificationName = "\\(mainBundleId).dataChanged" as CFString CFNotificationCenterPostNotification( notificationCenter, CFNotificationName(notificationName), nil, nil, true ) logger.info("Posted notification to main app") } }`; } /** * Main plugin for FinanceKit extension * Uses withDangerousMod to create extension files, which is necessary * because we need to create new files outside the normal mod system */ const withBackgroundDeliveryExtension = (config, props) => { const { appGroupIdentifier, extensionName = 'FinanceKitBackgroundExtension', extensionBundleIdentifier, } = props; // Use dangerous mod to create extension files config = (0, config_plugins_1.withDangerousMod)(config, [ 'ios', async (config) => { const { platformProjectRoot } = config.modRequest; const extensionPath = path.join(platformProjectRoot, extensionName); // Create extension directory if (!fs.existsSync(extensionPath)) { fs.mkdirSync(extensionPath, { recursive: true }); } // Write Swift file const swiftPath = path.join(extensionPath, 'BackgroundDeliveryExtension.swift'); const swiftContent = generateSwiftContent(appGroupIdentifier, config.ios?.bundleIdentifier); fs.writeFileSync(swiftPath, swiftContent); // Write Info.plist const infoPlistPath = path.join(extensionPath, 'Info.plist'); const infoPlistContent = getExtensionInfoPlist(extensionName); fs.writeFileSync(infoPlistPath, infoPlistContent); // Write entitlements const entitlementsPath = path.join(extensionPath, `${extensionName}.entitlements`); const entitlementsContent = getExtensionEntitlements(appGroupIdentifier); fs.writeFileSync(entitlementsPath, entitlementsContent); console.log(`✅ Created FinanceKit extension files at: ${extensionPath}`); return config; }, ]); // Use withXcodeProject to log instructions // Note: Actually adding the target to Xcode requires manual steps config = (0, config_plugins_1.withXcodeProject)(config, (config) => { console.warn(` ⚠️ FinanceKit Extension Manual Setup Required: Extension files have been created at: ios/${extensionName}/ To complete the setup in Xcode: 1. Open your .xcworkspace file 2. File > New > Target > App Extension 3. Select a basic App Extension template 4. Name it: ${extensionName} 5. Replace the generated files with the ones created by this plugin 6. In the extension target's Build Settings: - Set iOS Deployment Target to 17.4 - Add the same App Group as your main app 7. In Signing & Capabilities: - Add App Groups capability - Add FinanceKit capability The extension bundle ID should be: ${extensionBundleIdentifier || `${config.ios?.bundleIdentifier}.finance-background`} `); return config; }); return config; }; exports.withBackgroundDeliveryExtension = withBackgroundDeliveryExtension;