@eleven-am/nestjs-storage
Version:
A NestJS module for uploading files to cloud storage providers
258 lines • 8.87 kB
JavaScript
;
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