66
77const fs = require ( 'fs' ) ;
88const crypto = require ( 'crypto' ) ;
9+ const path = require ( 'path' ) ;
910
10- const TARGET = './google-services.json' ;
11+ const TARGETS = [
12+ './google-services.json' ,
13+ './android/app/google-services.json' ,
14+ ] ;
1115const BASE64 = process . env . GOOGLE_SERVICES_JSON_BASE64 || process . env . GOOGLE_SERVICES_BASE64 ; // legacy alias
1216const LEGACY_INLINE = process . env . GOOGLE_SERVICES_JSON ; // deprecated
1317
1418const isLikelyJson = ( str ) => ! ! str && str . trim ( ) . startsWith ( '{' ) && str . trim ( ) . endsWith ( '}' ) ;
1519const sha256 = ( d ) => crypto . createHash ( 'sha256' ) . update ( d ) . digest ( 'hex' ) . slice ( 0 , 12 ) ;
1620
1721function writeFileIfChanged ( path , content ) {
22+ const dir = require ( 'path' ) . dirname ( path ) ;
23+ fs . mkdirSync ( dir , { recursive : true } ) ;
24+
1825 if ( fs . existsSync ( path ) ) {
1926 const existing = fs . readFileSync ( path , 'utf8' ) ;
2027 if ( existing === content ) return false ; // unchanged
@@ -23,49 +30,86 @@ function writeFileIfChanged(path, content) {
2330 return true ;
2431}
2532
33+ function writeTargets ( content , sourceLabel ) {
34+ const results = TARGETS . map ( ( target ) => ( {
35+ target,
36+ changed : writeFileIfChanged ( target , content ) ,
37+ } ) ) ;
38+
39+ const summary = results
40+ . map ( ( r ) => `${ r . target } =${ r . changed ? 'written' : 'unchanged' } ` )
41+ . join ( ', ' ) ;
42+ console . log ( `✅ google-services.json from ${ sourceLabel } (${ summary } ) sha=${ sha256 ( content ) } ` ) ;
43+ }
44+
45+ function validateJson ( content ) {
46+ try {
47+ JSON . parse ( content ) ;
48+ } catch ( err ) {
49+ throw new Error ( `Content is not parseable JSON: ${ err . message || err } ` ) ;
50+ }
51+ }
52+
2653function handleBase64 ( b64 ) {
2754 const decoded = Buffer . from ( b64 , 'base64' ) . toString ( 'utf8' ) ;
2855 if ( ! isLikelyJson ( decoded ) ) {
2956 throw new Error ( 'Decoded content is not valid JSON' ) ;
3057 }
31- const changed = writeFileIfChanged ( TARGET , decoded ) ;
32- console . log ( `✅ google-services.json from BASE64 ( ${ changed ? 'written' : 'unchanged' } ) sha= ${ sha256 ( decoded ) } ` ) ;
58+ validateJson ( decoded ) ;
59+ writeTargets ( decoded , ' BASE64' ) ;
3360 return true ;
3461}
3562
3663function handleInline ( value ) {
3764 if ( isLikelyJson ( value ) ) {
38- const changed = writeFileIfChanged ( TARGET , value ) ;
39- console . log ( `✅ google-services.json from inline JSON ( ${ changed ? 'written' : 'unchanged' } ) sha= ${ sha256 ( value ) } ` ) ;
65+ validateJson ( value ) ;
66+ writeTargets ( value , ' inline JSON' ) ;
4067 return true ;
4168 }
4269 if ( fs . existsSync ( value ) ) {
4370 const fileContent = fs . readFileSync ( value , 'utf8' ) ;
4471 if ( ! isLikelyJson ( fileContent ) ) {
4572 console . warn ( '⚠️ Referenced file content does not look like JSON.' ) ;
4673 }
47- const changed = writeFileIfChanged ( TARGET , fileContent ) ;
48- console . log ( `✅ google-services.json copied from path ( ${ changed ? 'written' : 'unchanged' } ) sha= ${ sha256 ( fileContent ) } ` ) ;
74+ validateJson ( fileContent ) ;
75+ writeTargets ( fileContent , ' path' ) ;
4976 return true ;
5077 }
5178 console . warn ( '⚠️ Inline var not JSON and path not found:' , value ) ;
5279 return false ;
5380}
5481
82+ function failIfMissingForAndroidBuild ( ) {
83+ const androidAppPath = path . resolve ( './android/app/google-services.json' ) ;
84+ const androidProjectExists = fs . existsSync ( path . resolve ( './android/app/build.gradle' ) ) ;
85+
86+ if ( androidProjectExists && ! fs . existsSync ( androidAppPath ) ) {
87+ throw new Error (
88+ 'android/app/google-services.json is missing. Gradle google-services plugin requires this file.'
89+ ) ;
90+ }
91+ }
92+
5593function main ( ) {
5694 try {
5795 if ( BASE64 ) {
5896 handleBase64 ( BASE64 ) ;
97+ failIfMissingForAndroidBuild ( ) ;
5998 return ;
6099 }
61100 if ( LEGACY_INLINE ) {
62101 handleInline ( LEGACY_INLINE ) ;
102+ failIfMissingForAndroidBuild ( ) ;
63103 return ;
64104 }
65- if ( fs . existsSync ( TARGET ) ) {
66- const existing = fs . readFileSync ( TARGET , 'utf8' ) ;
67- console . log ( `ℹ️ Using existing google-services.json sha=${ sha256 ( existing ) } ` ) ;
105+ const rootTarget = './google-services.json' ;
106+ if ( fs . existsSync ( rootTarget ) ) {
107+ const existing = fs . readFileSync ( rootTarget , 'utf8' ) ;
108+ validateJson ( existing ) ;
109+ writeTargets ( existing , 'existing root file' ) ;
110+ failIfMissingForAndroidBuild ( ) ;
68111 } else {
112+ failIfMissingForAndroidBuild ( ) ;
69113 console . log ( 'ℹ️ No env provided; google-services.json not generated (expected in local dev or provided later).' ) ;
70114 }
71115 } catch ( err ) {
0 commit comments