UNPKG

@wellsite/version-generator

Version:
281 lines 11.7 kB
"use strict"; /** * Android version code generation utilities * Handles interaction with Google Play Developer API to get and increment version codes */ Object.defineProperty(exports, "__esModule", { value: true }); exports.DefaultAndroidExecutor = exports.DEFAULT_MAJOR_VERSION_INCREMENT = void 0; exports.getAndroidVersionCode = getAndroidVersionCode; exports.processReleases = processReleases; exports.getPlayStoreVersionInfo = getPlayStoreVersionInfo; exports.processTrackData = processTrackData; const googleapis_1 = require("googleapis"); const base64_1 = require("./base64"); /** * Default increment to add to version code when major version changes */ exports.DEFAULT_MAJOR_VERSION_INCREMENT = 10; /** * Default implementation of AndroidExecutor */ class DefaultAndroidExecutor { /** * Create an authenticated Google Play API client * * @param credentials - The parsed service account credentials * @returns The authenticated API client */ createApiClient(credentials) { // Create auth client with the parsed credentials const auth = new googleapis_1.google.auth.GoogleAuth({ credentials: credentials, scopes: ['https://www.googleapis.com/auth/androidpublisher'], }); // Create the Android Publisher client return googleapis_1.google.androidpublisher({ version: 'v3', auth, }); } /** * Query a specific track from the Play Store API * * @param packageName - The package name of the Android app * @param credentials - The parsed service account credentials * @param track - The track to query * @returns Promise resolving to the track data */ async queryTrack(packageName, credentials, track) { // Remove quotes if the package name is wrapped in quotes if (typeof packageName === 'string' && packageName.startsWith('"') && packageName.endsWith('"')) { packageName = packageName.slice(1, -1); } const androidPublisher = this.createApiClient(credentials); try { // Create a temporary edit to get track information const edit = await androidPublisher.edits.insert({ packageName, }); const editId = edit.data.id; if (!editId) { throw new Error('Failed to create edit'); } try { const trackInfo = await androidPublisher.edits.tracks.get({ packageName, editId, track, }); return { track, releases: trackInfo.data.releases || [], }; } finally { // Always try to delete the edit when done try { await androidPublisher.edits.delete({ packageName, editId, }); } catch (deleteError) { // Just log this error since we're already in an error handling block console.warn(`Error deleting edit: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`); } } } catch (error) { // If we can't get the specific track, return undefined // The caller can decide to fall back to queryAllTracks return undefined; } } /** * Query all tracks from the Play Store API * * @param packageName - The package name of the Android app * @param credentials - The parsed service account credentials * @returns Promise resolving to an array of track data */ async queryAllTracks(packageName, credentials) { // Remove quotes if the package name is wrapped in quotes if (typeof packageName === 'string' && packageName.startsWith('"') && packageName.endsWith('"')) { packageName = packageName.slice(1, -1); } const androidPublisher = this.createApiClient(credentials); try { // Create a temporary edit to get all tracks const edit = await androidPublisher.edits.insert({ packageName, }); const editId = edit.data.id; if (!editId) { throw new Error('Failed to create edit'); } try { const allTracks = await androidPublisher.edits.tracks.list({ packageName, editId, }); if (!allTracks.data.tracks) { return []; } return allTracks.data.tracks.map((track) => ({ track: track.track || undefined, // Convert null to undefined to match our interface releases: track.releases || [], })); } finally { // Always try to delete the edit when done try { await androidPublisher.edits.delete({ packageName, editId, }); } catch (deleteError) { // Just log this error since we're already in an error handling block console.warn(`Error deleting edit: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`); } } } catch (error) { throw new Error(`Failed to get track information: ${error instanceof Error ? error.message : String(error)}`); } } } exports.DefaultAndroidExecutor = DefaultAndroidExecutor; /** * Gets the Android version code from Google Play API * * @param options - Options for getting the Android version code * @param executor - The Android executor to use (optional) * @returns Promise resolving to the next Android version code to use */ async function getAndroidVersionCode(options, executor = new DefaultAndroidExecutor()) { // Check if Android version code generation is enabled if (!options.enabled) { return 0; // Return 0 to indicate not enabled (will be filtered out in index.ts) } // Check if required options are provided if (!options.packageName || !options.serviceAccountKey) { throw new Error('Missing required Android options: packageName and serviceAccountKey'); } try { // Use Google Play Developer API to get the current highest versionCode const currentVersionInfo = await getPlayStoreVersionInfo(options.packageName, options.serviceAccountKey, options.track, executor); if (!currentVersionInfo) { // If no version info is found, start with version code 1 // This is appropriate for first-time publishing return 1; } const currentVersionCode = currentVersionInfo.highestVersionCode; const currentMajorVersion = currentVersionInfo.majorVersion; // If the major version has changed, increment by a larger step if (options.currentMajorVersion > currentMajorVersion) { return currentVersionCode + (options.majorVersionIncrement || exports.DEFAULT_MAJOR_VERSION_INCREMENT); } else { // Otherwise, increment by 1 return currentVersionCode + 1; } } catch (error) { throw new Error(`Failed to get Android version code: ${error instanceof Error ? error.message : String(error)}`); } } /** * Helper function to process releases and find the highest version code * * @param releases - Array of releases to process * @param currentHighestVersionCode - Current highest version code found * @param currentMajorVersion - Current major version found * @returns Object containing the highest version code and associated major version */ function processReleases(releases, currentHighestVersionCode = 0, currentMajorVersion = 0) { let highestVersionCode = currentHighestVersionCode; let majorVersion = currentMajorVersion; for (const release of releases) { if (release.versionCodes && release.versionCodes.length > 0) { for (const versionCodeStr of release.versionCodes) { const versionCode = parseInt(versionCodeStr, 10); if (versionCode > highestVersionCode) { highestVersionCode = versionCode; // Try to extract major version from name if available if (release.name) { const versionMatch = release.name.match(/^(\d+)\./); if (versionMatch) { majorVersion = parseInt(versionMatch[1], 10); } } } } } } return { highestVersionCode, majorVersion }; } /** * Gets the version info from the Play Store * * @param packageName - The package name of the Android app * @param serviceAccountKey - The service account key for authentication * @param track - The track to get the version info from (optional) * @param executor - The Android executor to use (optional) * @returns Promise resolving to the version info */ async function getPlayStoreVersionInfo(packageName, serviceAccountKey, track, executor = new DefaultAndroidExecutor()) { try { // Parse the service account key const credentials = (0, base64_1.parseJSONValue)(serviceAccountKey); let trackData = []; // If a specific track is provided, try to get that track's info first if (track) { const specificTrackData = await executor.queryTrack(packageName, credentials, track); if (specificTrackData && specificTrackData.releases && specificTrackData.releases.length > 0) { trackData.push(specificTrackData); } } // If no specific track was provided or no data was found in the specific track, // query all tracks if (trackData.length === 0) { trackData = await executor.queryAllTracks(packageName, credentials); } // Process the track data to find the highest version code return processTrackData(trackData); } catch (error) { throw new Error(`Failed to get Play Store version info: ${error instanceof Error ? error.message : String(error)}`); } } /** * Process track data to find the highest version code and associated major version * * @param trackData - Array of track data to process * @returns The version info with highest version code and major version */ function processTrackData(trackData) { if (trackData.length === 0) { return undefined; } let highestVersionCode = 0; let majorVersion = 0; // Process each track to find the highest version code for (const track of trackData) { if (track.releases && track.releases.length > 0) { const result = processReleases(track.releases, highestVersionCode, majorVersion); if (result.highestVersionCode > highestVersionCode) { highestVersionCode = result.highestVersionCode; majorVersion = result.majorVersion; } else if (result.highestVersionCode === highestVersionCode && result.majorVersion > majorVersion) { majorVersion = result.majorVersion; } } } if (highestVersionCode === 0) { return undefined; } return { highestVersionCode, majorVersion }; } //# sourceMappingURL=android-version.js.map