@@ -18,99 +18,108 @@ const backupFileParamDescription = 'Filename to store backup. (e.g. backups/full
18
18
19
19
const nodePathParamKey = 'nodePath' ;
20
20
const nodePathParamDescription = 'Path to database node (has to be a collection) where import will to start (e.g. collectionA/docB/collectionC).' +
21
- ' Imports at root level if missing.' ;
21
+ ' Imports at root level if missing.' ;
22
+
23
+ const yesToImportParamKey = 'yes' ;
24
+ const yesToImportParamDescription = 'Unattended import without confirmation (like hitting "y" from the command line).' ;
22
25
23
26
commander . version ( packageInfo . version )
24
- . option ( `-a, --${ accountCredentialsPathParamKey } <path>` , accountCredentialsPathParamDescription )
25
- . option ( `-b, --${ backupFileParamKey } <path>` , backupFileParamDescription )
26
- . option ( `-n, --${ nodePathParamKey } <path>` , nodePathParamDescription )
27
- . parse ( process . argv ) ;
27
+ . option ( `-a, --${ accountCredentialsPathParamKey } <path>` , accountCredentialsPathParamDescription )
28
+ . option ( `-b, --${ backupFileParamKey } <path>` , backupFileParamDescription )
29
+ . option ( `-n, --${ nodePathParamKey } <path>` , nodePathParamDescription )
30
+ . option ( `-y, --${ yesToImportParamKey } ` , yesToImportParamDescription )
31
+ . parse ( process . argv ) ;
28
32
29
33
const accountCredentialsPath = commander [ accountCredentialsPathParamKey ] ;
30
34
if ( ! accountCredentialsPath ) {
31
- console . log ( colors . bold ( colors . red ( 'Missing: ' ) ) + colors . bold ( accountCredentialsPathParamKey ) + ' - ' + accountCredentialsPathParamDescription ) ;
32
- commander . help ( ) ;
33
- process . exit ( 1 ) ;
35
+ console . log ( colors . bold ( colors . red ( 'Missing: ' ) ) + colors . bold ( accountCredentialsPathParamKey ) + ' - ' + accountCredentialsPathParamDescription ) ;
36
+ commander . help ( ) ;
37
+ process . exit ( 1 ) ;
34
38
}
35
39
36
40
if ( ! fs . existsSync ( accountCredentialsPath ) ) {
37
- console . log ( colors . bold ( colors . red ( 'Account credentials file does not exist: ' ) ) + colors . bold ( accountCredentialsPath ) ) ;
38
- commander . help ( ) ;
39
- process . exit ( 1 )
41
+ console . log ( colors . bold ( colors . red ( 'Account credentials file does not exist: ' ) ) + colors . bold ( accountCredentialsPath ) ) ;
42
+ commander . help ( ) ;
43
+ process . exit ( 1 )
40
44
}
41
45
42
46
const backupFile = commander [ backupFileParamKey ] ;
43
47
if ( ! backupFile ) {
44
- console . log ( colors . bold ( colors . red ( 'Missing: ' ) ) + colors . bold ( backupFileParamKey ) + ' - ' + backupFileParamDescription ) ;
45
- commander . help ( ) ;
46
- process . exit ( 1 ) ;
48
+ console . log ( colors . bold ( colors . red ( 'Missing: ' ) ) + colors . bold ( backupFileParamKey ) + ' - ' + backupFileParamDescription ) ;
49
+ commander . help ( ) ;
50
+ process . exit ( 1 ) ;
47
51
}
48
52
49
53
if ( ! fs . existsSync ( backupFile ) ) {
50
- console . log ( colors . bold ( colors . red ( 'Backup file does not exist: ' ) ) + colors . bold ( backupFile ) ) ;
51
- commander . help ( ) ;
52
- process . exit ( 1 )
54
+ console . log ( colors . bold ( colors . red ( 'Backup file does not exist: ' ) ) + colors . bold ( backupFile ) ) ;
55
+ commander . help ( ) ;
56
+ process . exit ( 1 )
53
57
}
54
58
55
59
const nodePath = commander [ nodePathParamKey ] ;
56
60
57
61
const importPathPromise = getCredentialsFromFile ( accountCredentialsPath )
58
- . then ( credentials => {
59
- const db = getFirestoreDBReference ( credentials ) ;
60
- return getDBReferenceFromPath ( db , nodePath ) ;
61
- } ) ;
62
+ . then ( credentials => {
63
+ const db = getFirestoreDBReference ( credentials ) ;
64
+ return getDBReferenceFromPath ( db , nodePath ) ;
65
+ } ) ;
66
+
67
+ const unattendedConfirmation = commander [ yesToImportParamKey ] ;
62
68
63
69
Promise . all ( [ loadJsonFile ( backupFile ) , importPathPromise ] )
64
- . then ( ( res ) => {
65
- const [ data , pathReference ] = res ;
66
- const nodeLocation = ( < FirebaseFirestore . DocumentReference | FirebaseFirestore . CollectionReference > pathReference )
67
- . path || '[database root]' ;
68
- // For some reason, Firestore, DocumentReference, and CollectionReference interfaces
69
- // don't show a projectId property even though they do have them.
70
- // @todo : Remove any when that is fixed, or find the correct interface
71
- const projectID = ( < any > pathReference).projectId ||
72
- (< any > pathReference).firestore.projectId;
73
- const importText = `About to import data ${ backupFile } to the '${ projectID } ' firestore at '${ nodeLocation } '.`;
74
- console.log(`\n\n${ colors . bold ( colors . blue ( importText ) ) } `);
75
- console.log(colors.bgYellow(colors.blue(' === Warning: This will overwrite existing data. Do you want to proceed? === ')));
76
- return new Promise((resolve, reject) => {
77
- prompt . message = 'firestore-import' ;
78
- prompt . start ( ) ;
79
- prompt . get ( {
80
- properties : {
81
- response : {
82
- description : colors . red ( `Proceed with import? [y/N] ` )
83
- }
84
- }
85
- } , ( err : Error , result : any ) => {
86
- if ( err ) {
87
- return reject ( err ) ;
88
- }
89
- switch ( result . response . trim ( ) . toLowerCase ( ) ) {
90
- case 'y' :
91
- resolve ( res ) ;
92
- break ;
93
- default :
94
- reject ( 'Import aborted.' ) ;
95
- }
96
- } )
97
- } )
98
- } )
99
- . then ( ( res : any ) => {
100
- const [ data , pathReference ] = res ;
101
- return firestoreImport ( data , pathReference ) ;
102
- } )
103
- .then(() => {
104
- console . log ( colors . bold ( colors . green ( 'All done 🎉' ) ) ) ;
105
- } )
106
- .catch((error) => {
107
- if ( error instanceof Error ) {
108
- console . log ( colors . red ( `${ error . name } : ${ error . message } ` ) ) ;
109
- console . log ( colors . red ( error . stack as string ) ) ;
110
- process . exit ( 1 ) ;
111
- } else {
112
- console . log ( colors . red ( error ) ) ;
70
+ . then ( ( res ) => {
71
+ if ( unattendedConfirmation ) {
72
+ return res ;
73
+ }
74
+ const [ data , pathReference ] = res ;
75
+ const nodeLocation = ( < FirebaseFirestore . DocumentReference | FirebaseFirestore . CollectionReference > pathReference )
76
+ . path || '[database root]' ;
77
+ // For some reason, Firestore, DocumentReference, and CollectionReference interfaces
78
+ // don't show a projectId property even though they do have them.
79
+ // @todo : Remove any when that is fixed, or find the correct interface
80
+ const projectID = ( < any > pathReference).projectId ||
81
+ (< any > pathReference).firestore.projectId;
82
+ const importText = `About to import data ${ backupFile } to the '${ projectID } ' firestore at '${ nodeLocation } '.`;
83
+ console.log(`\n\n${ colors . bold ( colors . blue ( importText ) ) } `);
84
+ console.log(colors.bgYellow(colors.blue(' === Warning: This will overwrite existing data. Do you want to proceed? === ')));
85
+ return new Promise((resolve, reject) => {
86
+ prompt . message = 'firestore-import' ;
87
+ prompt . start ( ) ;
88
+ prompt . get ( {
89
+ properties : {
90
+ response : {
91
+ description : colors . red ( `Proceed with import? [y/N] ` )
92
+ }
93
+ }
94
+ } , ( err : Error , result : any ) => {
95
+ if ( err ) {
96
+ return reject ( err ) ;
113
97
}
114
- } ) ;
98
+ switch ( result . response . trim ( ) . toLowerCase ( ) ) {
99
+ case 'y' :
100
+ resolve ( res ) ;
101
+ break ;
102
+ default :
103
+ reject ( 'Import aborted.' ) ;
104
+ }
105
+ } )
106
+ } )
107
+ } )
108
+ . then ( ( res : any ) => {
109
+ const [ data , pathReference ] = res ;
110
+ return firestoreImport ( data , pathReference ) ;
111
+ } )
112
+ .then(() => {
113
+ console . log ( colors . bold ( colors . green ( 'All done 🎉' ) ) ) ;
114
+ } )
115
+ .catch((error) => {
116
+ if ( error instanceof Error ) {
117
+ console . log ( colors . red ( `${ error . name } : ${ error . message } ` ) ) ;
118
+ console . log ( colors . red ( error . stack as string ) ) ;
119
+ process . exit ( 1 ) ;
120
+ } else {
121
+ console . log ( colors . red ( error ) ) ;
122
+ }
123
+ } ) ;
115
124
116
125
0 commit comments