expo-finance-kit
Version:
Native Expo module for Apple FinanceKit - Access financial data from Apple Card and other accounts
191 lines • 6.17 kB
JavaScript
/**
* Authorization management module for Expo Finance Kit
* Handles FinanceKit authorization flows and status management
*/
import { Platform } from 'react-native';
import ExpoFinanceKit from '../ExpoFinanceKitModule';
import { FinanceKitErrorCode } from '../ExpoFinanceKit.types';
import { createFinanceKitError } from '../utils/errors';
/**
* Requests authorization to access financial data
* @returns Promise resolving to authorization result
*/
export async function requestAuthorization() {
if (Platform.OS === 'android') {
return {
granted: false,
status: 'unavailable',
};
}
try {
const granted = await ExpoFinanceKit.requestAuthorization();
const status = await ExpoFinanceKit.getAuthorizationStatus();
return {
granted,
status: status,
};
}
catch (error) {
console.error('Error requesting FinanceKit authorization:', error);
return {
granted: false,
status: 'denied',
};
}
}
/**
* Gets current authorization status
* @returns Promise resolving to current authorization status
*/
export async function getAuthorizationStatus() {
if (Platform.OS === 'android') {
return 'unavailable';
}
try {
const status = await ExpoFinanceKit.getAuthorizationStatus();
return status;
}
catch (error) {
console.error('Error getting authorization status:', error);
return 'unavailable';
}
}
/**
* Checks if FinanceKit is available on the device
* @returns Boolean indicating availability
*/
export function isFinanceKitAvailable() {
if (Platform.OS === 'android') {
return false;
}
return ExpoFinanceKit.isAvailable || false;
}
/**
* Ensures user has authorized access before proceeding
* @param requestIfNeeded - Whether to request authorization if not determined
* @returns Promise resolving to boolean indicating authorization status
*/
export async function ensureAuthorized(requestIfNeeded = true) {
const status = await getAuthorizationStatus();
if (status === 'authorized') {
return true;
}
if (status === 'notDetermined' && requestIfNeeded) {
const { granted } = await requestAuthorization();
return granted;
}
return false;
}
/**
* Authorization status change listener manager
*/
class AuthorizationListener {
listeners = new Map();
/**
* Adds a listener for authorization status changes
* @param callback - Function to call when status changes
* @returns Function to remove the listener
*/
addStatusChangeListener(callback) {
const listenerId = Math.random().toString(36).substring(2, 11);
const listener = (payload) => {
callback({
...payload,
timestamp: payload.timestamp || Date.now(),
});
};
this.listeners.set(listenerId, listener);
if (ExpoFinanceKit.addListener) {
ExpoFinanceKit.addListener('onAuthorizationStatusChanged', listener);
}
return () => {
this.removeListener(listenerId);
};
}
/**
* Removes a specific listener
* @param listenerId - ID of the listener to remove
*/
removeListener(listenerId) {
const listener = this.listeners.get(listenerId);
if (listener && ExpoFinanceKit.removeListener) {
ExpoFinanceKit.removeListener('onAuthorizationStatusChanged', listener);
this.listeners.delete(listenerId);
}
}
/**
* Removes all authorization listeners
*/
removeAllListeners() {
if (ExpoFinanceKit.removeAllListeners) {
ExpoFinanceKit.removeAllListeners('onAuthorizationStatusChanged');
}
this.listeners.clear();
}
}
export const authorizationListener = new AuthorizationListener();
/**
* Waits for authorization with timeout
* @param timeoutMs - Maximum time to wait in milliseconds
* @returns Promise resolving to authorization result
*/
export async function waitForAuthorization(timeoutMs = 30000) {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
removeListener();
reject(createFinanceKitError(FinanceKitErrorCode.Unknown, 'Authorization timeout'));
}, timeoutMs);
const removeListener = authorizationListener.addStatusChangeListener((payload) => {
if (payload.status !== 'notDetermined') {
clearTimeout(timeout);
removeListener();
resolve({
granted: payload.status === 'authorized',
status: payload.status,
});
}
});
// Check current status immediately
getAuthorizationStatus().then(status => {
if (status !== 'notDetermined') {
clearTimeout(timeout);
removeListener();
resolve({
granted: status === 'authorized',
status,
});
}
});
});
}
/**
* Gets human-readable description for authorization status
* @param status - Authorization status
* @returns Human-readable description
*/
export function getAuthorizationStatusDescription(status) {
switch (status) {
case 'authorized':
return 'Access to financial data has been granted';
case 'denied':
return 'Access to financial data has been denied';
case 'notDetermined':
return 'Authorization has not been requested yet';
case 'unavailable':
return 'FinanceKit is not available on this device';
default:
return 'Unknown authorization status';
}
}
/**
* Checks if authorization can be requested
* @returns Promise resolving to boolean
*/
export async function canRequestAuthorization() {
if (!isFinanceKitAvailable()) {
return false;
}
const status = await getAuthorizationStatus();
return status === 'notDetermined';
}
//# sourceMappingURL=authorization.js.map