UNPKG

@eleven-am/nestjs-storage

Version:

A NestJS module for uploading files to cloud storage providers

258 lines 8.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DropboxStorage = void 0; const baseStorage_1 = require("./baseStorage"); const zod_1 = require("zod"); const getMimetype_1 = require("../lib/getMimetype"); const makeRequest_1 = require("../lib/makeRequest"); const dropboxFileSchema = zod_1.z.object({ '.tag': zod_1.z.union([zod_1.z.literal('file'), zod_1.z.literal('folder')]), name: zod_1.z.string(), id: zod_1.z.string(), path_lower: zod_1.z.string(), path_display: zod_1.z.string(), client_modified: zod_1.z.string(), size: zod_1.z.number().optional(), }); const dropboxGetFilesResponseSchema = zod_1.z.object({ entries: zod_1.z.array(dropboxFileSchema), has_more: zod_1.z.boolean(), cursor: zod_1.z.string(), }); const dropboxTokenSchema = zod_1.z.object({ access_token: zod_1.z.string(), expires_in: zod_1.z.number(), refresh_token: zod_1.z.string(), }); class DropboxStorage extends baseStorage_1.BaseStorage { constructor(options) { super(options.provider); this.credentials = { clientId: options.options.clientId, clientSecret: options.options.clientSecret, }; this.refreshToken = options.options.refreshToken; } async createFolder(path) { const params = { path: 'https://api.dropboxapi.com/2/files/create_folder_v2', query: { path: `${path}`, }, }; const data = await this.makeRequest(params, dropboxFileSchema); return this.parseFile(data); } async deleteFileOrFolder(fileId) { const params = { path: 'https://api.dropboxapi.com/2/files/delete_v2', query: { path: `${fileId}`, }, }; await this.makeRequest(params, dropboxFileSchema); return true; } async getFileOrFolder(fileId) { const params = { path: 'https://api.dropboxapi.com/2/files/get_metadata', query: { path: `${fileId}`, }, }; const data = await this.makeRequest(params, dropboxFileSchema); return this.parseFile(data); } async moveFileOrFolder(fileId, newPath) { const params = { path: 'https://api.dropboxapi.com/2/files/move_v2', query: { from_path: fileId, to_path: newPath, }, }; const data = await this.makeRequest(params, dropboxFileSchema); return this.parseFile(data); } async putFile(path, data) { const token = await this.authenticate(); const response = await fetch('https://content.dropboxapi.com/2/files/upload', { method: 'POST', headers: { Authorization: `Bearer ${token.access_token}`, 'Content-Type': 'application/octet-stream', 'Dropbox-API-Arg': JSON.stringify({ path, mode: 'overwrite', }), }, body: data, }); try { const json = await response.json(); const dropboxFile = dropboxFileSchema.parse(json); return this.parseFile(dropboxFile); } catch (e) { throw new Error('Failed to upload file to Dropbox'); } } async readFile(fileId) { const token = await this.authenticate(); const options = { method: 'POST', headers: { authorization: `Bearer ${token.access_token}`, 'Dropbox-API-Arg': JSON.stringify({ path: fileId, }), 'Content-Type': 'application/octet-stream', }, }; return new Promise((resolve, reject) => { fetch('https://content.dropboxapi.com/2/files/download', options) .then((response) => { if (!response.ok) { reject(response); } resolve(response.body); }) .catch((error) => { reject(error); }); }); } async readFolder(folderId) { const query = { path: folderId, include_media_info: true, include_deleted: false, include_has_explicit_shared_members: false, include_mounted_folders: true, include_non_downloadable_files: true, }; const params = { path: 'https://api.dropboxapi.com/2/files/list_folder', query, }; const data = await this.makeRequest(params, dropboxGetFilesResponseSchema); return data.entries.map((file) => this.parseFile(file)); } readRootFolder() { return this.readFolder(''); } renameFileOrFolder(fileId, newName) { return this.moveFileOrFolder(fileId, newName); } getSignedUrl(fileId) { const params = { path: 'https://api.dropboxapi.com/2/files/get_temporary_link', query: { path: fileId, }, }; return new Promise((resolve, reject) => { this.makeRequest(params, zod_1.z.object({ link: zod_1.z.string(), metadata: dropboxFileSchema, })) .then((data) => { resolve(data.link); }) .catch((error) => { reject(error); }); }); } async streamFile(fileId, range) { const token = await this.authenticate(); const options = { method: 'POST', headers: { authorization: `Bearer ${token.access_token}`, 'Dropbox-API-Arg': JSON.stringify({ path: fileId, }), 'Content-Type': 'application/octet-stream', Range: range, }, }; return new Promise((resolve, reject) => { fetch('https://content.dropboxapi.com/2/files/download', options) .then((response) => { if (!response.ok) { reject(response); } resolve({ stream: response.body, headers: { contentType: response.headers.get('Content-Type') || '', contentLength: response.headers.get('Content-Length') || '', contentRange: response.headers.get('Content-Range') || '', contentDisposition: response.headers.get('Content-Disposition') || '', }, }); }) .catch((error) => { reject(error); }); }); } parseFile(file) { return { name: file.name, path: file.path_lower, size: file.size || 0, mimeType: (0, getMimetype_1.getMimeType)(file.name), isFolder: file['.tag'] === 'folder', modifiedAt: new Date(file.client_modified), }; } makeRequest({ path, query }, schema) { return new Promise((resolve, reject) => { this.authenticate() .then((token) => { const params = { address: `https://api.dropboxapi.com/2${path}`, method: 'POST', headers: { Authorization: `Bearer ${token.access_token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(query), }; return (0, makeRequest_1.makeRequest)(params, schema); }) .then((data) => { resolve(data); }) .catch((error) => { reject(error); }); }); } async authenticate() { if (this.token && this.token.expires_in > Date.now()) { return this.token; } const query = { grant_type: 'refresh_token', refresh_token: this.refreshToken, client_id: this.credentials.clientId, client_secret: this.credentials.clientSecret, }; const response = await (0, makeRequest_1.makeRequest)({ address: 'https://api.dropboxapi.com/oauth2/token', method: 'GET', query, }, dropboxTokenSchema); const token = { ...response, expires_in: Date.now() + response.expires_in * 1000, }; this.token = token; return token; } } exports.DropboxStorage = DropboxStorage; //# sourceMappingURL=dropboxStorage.js.map