@@ -5,14 +5,9 @@ import Datastore from '@google-cloud/datastore';
55
66import GoogleCloudStorageHandler from './storage' ;
77import StorageHelper from './storage-helper' ;
8- import type { ConfigMemory } from './storage-helper' ;
98import type { Logger , Callback } from '@verdaccio/types' ;
109import type { ILocalData } from '@verdaccio/local-storage' ;
11-
12- const GOOGLE_OPTIONS : any = {
13- projectId : process . env . GC_PROJECT_ID ,
14- keyFilename : process . env . GC_KEY_FILE
15- } ;
10+ import type { ConfigGoogleStorage , GoogleCloudOptions , GoogleDataStorage } from '../types' ;
1611
1712declare type GoogleDataStorage = {
1813 secret : string ,
@@ -21,25 +16,57 @@ declare type GoogleDataStorage = {
2116} ;
2217
2318class GoogleCloudDatabase implements ILocalData {
19+ helper : any ;
2420 path : string ;
2521 logger : Logger ;
2622 data : GoogleDataStorage ;
27- bucketName : string ;
28- config : ConfigMemory ;
2923 locked : boolean ;
30- datastore : any ;
31- key : string ;
32- helper : any ;
24+ config : ConfigGoogleStorage ;
25+ kind : string ;
26+ bucketName : string ;
27+ keyFilename : string ;
28+ GOOGLE_OPTIONS : GoogleCloudOptions ;
3329
34- constructor ( config : ConfigMemory , options : any ) {
30+ constructor ( config : ConfigGoogleStorage , options : any ) {
31+ if ( ! config ) {
32+ throw new Error ( 'google cloud storage missing config. Add `store.google-cloud` to your config file' ) ;
33+ }
3534 this . config = config ;
3635 this . logger = options . logger ;
37- this . key = config . metadataDatabaseKey || 'VerdaccioDataStore' ;
38- this . bucketName = config . bucketName || 'verdaccio-plugin' ;
36+ this . kind = config . kind || 'VerdaccioDataStore' ;
37+ // if (!this.keyFilename) {
38+ // throw new Error('Google Storage requires a a key file');
39+ // }
40+ this . bucketName = config . bucket ;
41+ if ( ! this . bucketName ) {
42+ throw new Error ( 'Google Cloud Storage requires a bucket name, please define one.' ) ;
43+ }
3944 this . data = this . _createEmtpyDatabase ( ) ;
4045 this . helper = new StorageHelper ( this . data . datastore , this . data . storage ) ;
4146 }
4247
48+ _getGoogleOptions ( config : ConfigGoogleStorage ) : GoogleCloudOptions {
49+ const GOOGLE_OPTIONS : GoogleCloudOptions = { } ;
50+
51+ if ( ! config . projectId || typeof config . projectId !== 'string' ) {
52+ throw new Error ( 'Google Cloud Storage requires a ProjectId.' ) ;
53+ }
54+
55+ GOOGLE_OPTIONS . projectId = config . projectId || process . env . GOOGLE_CLOUD_VERDACCIO_PROJECT_ID ;
56+
57+ const keyFileName = config . keyFilename || process . env . GOOGLE_CLOUD_VERDACCIO_KEY ;
58+ if ( keyFileName ) {
59+ GOOGLE_OPTIONS . keyFilename = keyFileName ;
60+ this . logger . warn ( 'Using credentials in a file might be un-secure and is recommended for local development' ) ;
61+ }
62+ // const GOOGLE_OPTIONS: GoogleCloudOptions = {
63+ // projectId: 'verdaccio-01',
64+ // keyFilename: './verdaccio-01-56f693e3aab0.json'
65+ // };
66+ this . logger . warn ( { content : JSON . stringify ( GOOGLE_OPTIONS ) } , 'Google storage settings: @{content}' ) ;
67+ return GOOGLE_OPTIONS ;
68+ }
69+
4370 getSecret ( ) : Promise < any > {
4471 return Promise . resolve ( this . data . secret ) ;
4572 }
@@ -71,7 +98,7 @@ class GoogleCloudDatabase implements ILocalData {
7198 async deleteItem ( name : string , item : any ) {
7299 try {
73100 const datastore = this . data . datastore ;
74- const key = datastore . key ( [ this . key , datastore . int ( item . id ) ] ) ;
101+ const key = datastore . key ( [ this . kind , datastore . int ( item . id ) ] ) ;
75102 const deleted = await datastore . delete ( key ) ;
76103 return deleted ;
77104 } catch ( err ) {
@@ -86,10 +113,12 @@ class GoogleCloudDatabase implements ILocalData {
86113 return new Error ( 'not found' ) ;
87114 } else if ( deletedItems [ 0 ] [ 0 ] . indexUpdates > 0 ) {
88115 return null ;
116+ } else {
117+ return new Error ( 'this should not happen' ) ;
89118 }
90119 } ;
91120 this . helper
92- . getEntities ( this . key )
121+ . getEntities ( this . kind )
93122 . then ( async entities => {
94123 for ( const item of entities ) {
95124 if ( item . name === name ) {
@@ -105,7 +134,7 @@ class GoogleCloudDatabase implements ILocalData {
105134 }
106135
107136 get ( cb : Callback ) {
108- const query = this . helper . datastore . createQuery ( this . key ) ;
137+ const query = this . helper . datastore . createQuery ( this . kind ) ;
109138 this . helper . runQuery ( query ) . then ( data => {
110139 const names = data [ 0 ] . reduce ( ( accumulator , task ) => {
111140 accumulator . push ( task . name ) ;
@@ -124,8 +153,8 @@ class GoogleCloudDatabase implements ILocalData {
124153 }
125154
126155 _createEmtpyDatabase ( ) : GoogleDataStorage {
127- const datastore = new Datastore ( GOOGLE_OPTIONS ) ;
128- const storage = new Storage ( GOOGLE_OPTIONS ) ;
156+ const datastore = new Datastore ( this . _getGoogleOptions ( this . config ) ) ;
157+ const storage = new Storage ( this . _getGoogleOptions ( this . config ) ) ;
129158
130159 const list : any = [ ] ;
131160 const files : any = { } ;
0 commit comments