UNPKG

@softvisio/core

Version:
285 lines (232 loc) • 9 kB
import Oauth from "#lib/api/google/oauth"; import fetch from "#lib/fetch"; import Headers from "#lib/http/headers"; import StreamMultipart from "#lib/stream/multipart"; const DEFAULT_PERMISSION = "fullControl"; const SCOPES = { "readOnly": "https://www.googleapis.com/auth/devstorage.read_only", "readWrite": "https://www.googleapis.com/auth/devstorage.read_write", "fullControl": "https://www.googleapis.com/auth/devstorage.full_control", "cloudPlatformReadOnly": "https://www.googleapis.com/auth/cloud-platform.read-only", "cloudPlatform": "https://www.googleapis.com/auth/cloud-platform", }; const API_URL = "https://storage.googleapis.com/storage/v1/", UPLOAD_URL = "https://storage.googleapis.com/upload/storage/v1/", DOWNLOAD_URL = "https://storage.googleapis.com/"; export default class GoogleCloudStorage { #oauth; #permission; constructor ( key, { permission } = {} ) { this.#permission = permission || DEFAULT_PERMISSION; this.#oauth = new Oauth( key, SCOPES[ this.#permission ] ); } // properties get permission () { return this.#permission; } // public // https://cloud.google.com/storage/docs/json_api/v1/buckets/insert async createBucket ( bucket, { predefinedAcl, predefinedDefaultObjectAcl } = {} ) { return this.#request( API_URL + "b", { "params": { "project": this.#oauth.projectId, ...( predefinedAcl && { predefinedAcl } ), ...( predefinedDefaultObjectAcl && { predefinedDefaultObjectAcl } ), }, "request": { "method": "post", "headers": { "content-type": "application/json", }, "body": JSON.stringify( { "name": bucket, } ), }, } ); } // https://cloud.google.com/storage/docs/json_api/v1/buckets/list async getBuckets () { return this.#request( API_URL + "b", { "params": { "project": this.#oauth.projectId, }, } ); } // https://cloud.google.com/storage/docs/json_api/v1/buckets/get async getBucket ( bucket ) { return this.#request( API_URL + "b/" + encodeURIComponent( bucket ) ); } // https://cloud.google.com/storage/docs/json_api/v1/buckets/delete async deleteBucket ( bucket ) { return this.#request( API_URL + "b/" + encodeURIComponent( bucket ), { "request": { "method": "delete", }, } ); } // https://cloud.google.com/storage/docs/json_api/v1/objects/insert async uploadFile ( path, file, { predefinedAcl, metadata } = {} ) { const { bucket, name } = this.#parsePath( path ); metadata ||= {}; if ( file.type ) metadata.contentType ||= file.type; const stream = new StreamMultipart( "related" ); stream.append( JSON.stringify( metadata ), { "type": "application/json" } ); stream.append( file.stream(), { "type": file.type } ); return this.#request( UPLOAD_URL + `b/${ encodeURIComponent( bucket ) }/o`, { "params": { name, "uploadType": "multipart", ...( predefinedAcl && { predefinedAcl } ), }, "request": { "method": "post", "body": stream, }, } ); } // https://cloud.google.com/storage/docs/json_api/v1/objects/list async getFiles ( bucket ) { return this.#request( API_URL + `b/${ encodeURIComponent( bucket ) }/o` ); } // https://cloud.google.com/storage/docs/json_api/v1/objects/get async getFile ( path ) { const { bucket, name } = this.#parsePath( path ); const res = await this.#request( API_URL + `b/${ encodeURIComponent( bucket ) }/o/${ encodeURIComponent( name ) }`, { "returnResult": true, "params": { "alt": "media", }, } ); if ( res.ok ) { const tmpFile = await res.tmpFile().catch( e => null ); if ( !tmpFile ) { return result( 500 ); } else { return result( 200, tmpFile ); } } else { return result( res.status ); } } async getBuffer ( path ) { const { bucket, name } = this.#parsePath( path ); const res = await this.#request( API_URL + `b/${ encodeURIComponent( bucket ) }/o/${ encodeURIComponent( name ) }`, { "returnResult": true, "params": { "alt": "media", }, } ); if ( res.ok ) { const buffer = await res.buffer().catch( e => null ); if ( !buffer ) { return result( 500 ); } else { return result( 200, buffer ); } } else { return result( res.status ); } } async getFileHttpResponse ( path, { headers } = {} ) { const { bucket, name } = this.#parsePath( path ); if ( headers ) { if ( headers instanceof Headers ) { headers = { ...headers.toJSON() }; } delete headers.host; delete headers.referer; } const res = await this.#request( DOWNLOAD_URL + `${ encodeURIComponent( bucket ) }/${ encodeURIComponent( name ) }`, { "returnResult": true, "request": { headers, }, } ); return res; } // https://cloud.google.com/storage/docs/json_api/v1/objects/get async getFileMetadata ( path ) { const { bucket, name } = this.#parsePath( path ); return this.#request( API_URL + `b/${ encodeURIComponent( bucket ) }/o/${ encodeURIComponent( name ) }`, { "params": { "alt": "json", }, } ); } // https://cloud.google.com/storage/docs/json_api/v1/objects/patch async patchFileMetadata ( path, metadata ) { const { bucket, name } = this.#parsePath( path ); return this.#request( API_URL + `b/${ encodeURIComponent( bucket ) }/o/${ encodeURIComponent( name ) }`, { "request": { "method": "patch", "headers": { "content-type": "application/json", }, "body": JSON.stringify( metadata ), }, } ); } // https://cloud.google.com/storage/docs/json_api/v1/objects/update async updateFileMetadata ( path, metadata ) { const { bucket, name } = this.#parsePath( path ); return this.#request( API_URL + `b/${ encodeURIComponent( bucket ) }/o/${ encodeURIComponent( name ) }`, { "request": { "method": "put", "headers": { "content-type": "application/json", }, "body": JSON.stringify( metadata ), }, } ); } // https://cloud.google.com/storage/docs/json_api/v1/objects/delete async deleteFile ( path ) { const { bucket, name } = this.#parsePath( path ); return this.#request( API_URL + `b/${ encodeURIComponent( bucket ) }/o/${ encodeURIComponent( name ) }`, { "request": { "method": "delete", }, } ); } // https://cloud.google.com/storage/docs/json_api/v1/objects/copy async copyFile ( from, to ) { from = this.#parsePath( from ); to = this.#parsePath( to ); return this.#request( API_URL + `b/${ encodeURIComponent( from.bucket ) }/o/${ encodeURIComponent( from.name ) }/copyTo/b/${ encodeURIComponent( to.bucket ) }/o/${ encodeURIComponent( to.name ) }`, { "request": { "method": "post", }, } ); } // private #parsePath ( path ) { const idx = path.indexOf( "/" ); return { "bucket": path.slice( 0, idx ), "name": path.slice( idx + 1 ), }; } async #request ( url, { returnResult, params, request = {} } = {} ) { const token = await this.#oauth.getToken(); if ( !token.ok ) return token; url = new URL( url ); if ( params ) url.search = new URLSearchParams( params ); request.headers ||= {}; request.headers.authorization = `Bearer ${ token.data }`; const res = await fetch( url, request ); if ( returnResult ) return res; if ( res.headers.contentType.type === "application/json" ) { var data = await res.json().catch( e => null ); } if ( res.ok ) { return result( 200, data ); } else { return result( [ res.status, data?.error?.message || res.statusText ] ); } } }