UNPKG

@itwin/object-storage-google

Version:

Object storage implementation using Google Cloud Storage

158 lines 6.35 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); exports.StorageWrapper = void 0; const stream_1 = require("stream"); const storage_1 = require("@google-cloud/storage"); const internal_1 = require("@itwin/object-storage-core/lib/common/internal"); const internal_2 = require("@itwin/object-storage-core/lib/server/internal"); class StorageWrapper { _storage; _config; constructor(_storage, _config) { this._storage = _storage; this._config = _config; } async downloadFile(reference, destination) { const [buffer] = await this.fileObject(reference).download({ destination, }); return buffer; } async uploadFile(reference, data, metadata, headers, chunkSize) { const options = { metadata: { ...metadata }, chunkSize: chunkSize, }; options.contentType = headers?.contentType; options.gzip = headers?.contentEncoding === "gzip"; if (typeof data === "string") { const uploadOptions = { ...options }; uploadOptions.destination = (0, internal_1.buildObjectKey)(reference); await this.bucketObject().upload(data, uploadOptions); } else { const saveData = data instanceof stream_1.Readable ? await (0, internal_2.streamToBuffer)(data) : data ?? ""; await this.fileObject(reference).save(saveData, options); } if (metadata || headers?.cacheControl || headers?.contentEncoding) { const [updatedMetadata] = await this.fileObject(reference).getMetadata(); updatedMetadata.metadata = { ...updatedMetadata.metadata, ...metadata }; if (headers?.cacheControl) updatedMetadata.cacheControl = headers.cacheControl; if (headers?.contentEncoding) updatedMetadata.contentEncoding = headers.contentEncoding; await this.fileObject(reference).setMetadata(updatedMetadata); } } async getFilesNextPage(options) { const [files, nextPageToken] = await this.bucketObject().getFiles({ prefix: options.directory.baseDirectory, maxResults: options.maxPageSize, pageToken: options.continuationToken, }); return { entities: files.map((file) => { const parts = file.name.split("/"); const reference = { objectName: parts.length > 1 ? parts[parts.length - 1] : "", baseDirectory: parts[0] || options.directory.baseDirectory, }; if (parts.length > 2) { reference.relativeDirectory = parts .slice(1, parts.length - 1) .join("/"); } return reference; }), next: nextPageToken?.pageToken ? () => this.getFilesNextPage({ ...options, continuationToken: nextPageToken.pageToken, }) : undefined, }; } async deleteFile(reference) { try { await this.fileObject(reference).delete(); } catch (error) { if (error instanceof storage_1.ApiError && error.code === 404) return; throw error; } } async copyFile(sourceBucket, sourceReference, destinationReference) { await this._storage .bucket(sourceBucket) .file((0, internal_1.buildObjectKey)(sourceReference)) .copy(this.fileObject(destinationReference)); } async getSignedUrl(action, reference, expiry) { const expires = (0, internal_2.getExpiryDate)(expiry); const [url] = await this.fileObject(reference).getSignedUrl({ action, expires, version: "v4", }); return url; } async updateMetadata(reference, metadata) { const [updatedMetadata] = await this.fileObject(reference).getMetadata(); if (updatedMetadata.metadata == null) updatedMetadata.metadata = {}; for (const key of Object.keys(updatedMetadata.metadata)) { if (key in metadata) continue; updatedMetadata.metadata[key] = null; } for (const key of Object.keys(metadata)) { updatedMetadata.metadata[key] = metadata[key]; } await this.fileObject(reference).setMetadata(updatedMetadata); } async getObjectProperties(reference) { const [fileMetadata] = await this.fileObject(reference).getMetadata(); const metadata = {}; if (fileMetadata.metadata) { for (const key of Object.keys(fileMetadata.metadata)) { metadata[key] = String(fileMetadata.metadata[key]); } } return { reference, lastModified: fileMetadata.updated ? new Date(fileMetadata.updated) : new Date(), size: Number(fileMetadata.size), metadata: metadata, contentType: fileMetadata.contentType, contentEncoding: fileMetadata.contentEncoding, cacheControl: fileMetadata.cacheControl, }; } async fileExists(reference) { try { await this.fileObject(reference).get(); return true; // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error) { if (error instanceof storage_1.ApiError && error.code === 404) return false; throw error; } } bucketObject() { return this._storage.bucket(this._config.bucketName); } fileObject(reference) { return this.bucketObject().file((0, internal_1.buildObjectKey)(reference)); } } exports.StorageWrapper = StorageWrapper; //# sourceMappingURL=StorageWrapper.js.map