Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@internxt/sdk",
"author": "Internxt <hello@internxt.com>",
"version": "1.15.1",
"version": "1.15.2",
"description": "An sdk for interacting with Internxt's services",
"repository": {
"type": "git",
Expand Down
114 changes: 40 additions & 74 deletions src/network/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,6 @@ const uuidValidate = (str: string): boolean => UUID_REGEX.test(str);

export * from './types';

export class DuplicatedIndexesError extends Error {
constructor() {
super('Duplicated indexes found');

Object.setPrototypeOf(this, DuplicatedIndexesError.prototype);
}
}

export class InvalidFileIndexError extends Error {
constructor() {
super('Invalid file index');
Expand All @@ -35,14 +27,6 @@ export class InvalidFileIndexError extends Error {
}
}

export class InvalidUploadIndexError extends Error {
constructor() {
super('Invalid upload index');

Object.setPrototypeOf(this, InvalidUploadIndexError.prototype);
}
}

export class InvalidUploadSizeError extends Error {
constructor() {
super('Invalid size');
Expand Down Expand Up @@ -89,47 +73,28 @@ export class Network {
return this.auth;
}

startUpload(bucketId: string, payload: StartUploadPayload, parts = 1): Promise<StartUploadResponse> {
let totalSize = 0;

for (const { index, size } of payload.uploads) {
if (index < 0) {
throw new InvalidUploadIndexError();
}
if (size < 0) {
throw new InvalidUploadSizeError();
}
totalSize += size;
async startUpload(bucketId: string, fileSize: number, signal?: AbortSignal, parts = 1): Promise<StartUploadResponse> {
if (fileSize <= 0) {
throw new InvalidUploadSizeError();
}

const MB100 = 100 * 1024 * 1024;
if (totalSize < MB100 && parts > 1) {
if (fileSize < MB100 && parts > 1) {
throw new FileTooSmallForMultipartError();
}

if (!Number.isInteger(parts) || parts < 1) {
throw new InvalidMultipartValueError();
}

const uploadIndexesWithoutDuplicates = new Set(payload.uploads.map((upload) => upload.index));

if (uploadIndexesWithoutDuplicates.size < payload.uploads.length) {
throw new DuplicatedIndexesError();
}

return Network.startUpload(
bucketId,
payload,
{
client: this.client,
appDetails: this.appDetails,
auth: this.auth,
},
parts,
);
return await this.startUploadRequest(bucketId, { uploads: [{ index: 0, size: fileSize }] }, signal, parts);
}

finishUpload(bucketId: string, payload: FinishUploadPayload): Promise<FinishUploadResponse> {
async finishUpload(
bucketId: string,
payload: FinishUploadPayload,
signal?: AbortSignal,
): Promise<FinishUploadResponse> {
const { index, shards } = payload;
if (!isHexString(index) || index.length !== 64) {
throw new InvalidFileIndexError();
Expand All @@ -141,14 +106,14 @@ export class Network {
}
}

return Network.finishUpload(bucketId, payload, {
client: this.client,
appDetails: this.appDetails,
auth: this.auth,
});
return await this.finishUploadRequest(bucketId, payload, signal);
}

finishMultipartUpload(bucketId: string, payload: FinishMultipartUploadPayload): Promise<FinishUploadResponse> {
async finishMultipartUpload(
bucketId: string,
payload: FinishMultipartUploadPayload,
signal?: AbortSignal,
): Promise<FinishUploadResponse> {
const { index, shards } = payload;
if (!isHexString(index) || index.length !== 64) {
throw new InvalidFileIndexError();
Expand All @@ -167,15 +132,11 @@ export class Network {
}
}

return Network.finishUpload(bucketId, payload, {
client: this.client,
appDetails: this.appDetails,
auth: this.auth,
});
return await this.finishUploadRequest(bucketId, payload, signal);
}

getDownloadLinks(bucketId: string, fileId: string, token?: string): Promise<GetDownloadLinksResponse> {
return Network.getDownloadLinks(
async getDownloadLinks(bucketId: string, fileId: string, token?: string): Promise<GetDownloadLinksResponse> {
return await Network.getDownloadLinks(
bucketId,
fileId,
{
Expand All @@ -200,17 +161,13 @@ export class Network {
* @param bucketId
* @param uploads
*/
static startUpload(
bucketId: string,
payload: StartUploadPayload,
{ client, appDetails, auth }: NetworkRequestConfig,
parts = 1,
) {
const headers = Network.headersWithBasicAuth(appDetails, auth);
return client.post<StartUploadResponse>(
async startUploadRequest(bucketId: string, payload: StartUploadPayload, signal?: AbortSignal, parts = 1) {
const headers = Network.headersWithBasicAuth(this.appDetails, this.auth);
return await this.client.post<StartUploadResponse>(
`/v2/buckets/${bucketId}/files/start?multiparts=${parts}`,
payload,
headers,
signal,
);
}

Expand All @@ -220,21 +177,26 @@ export class Network {
* @param index
* @param shards
*/
private static finishUpload(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function was static to be able to be called finishUpload too, however, I think it's easier to read if we use different names (this one just makes the request), and by making it non static we can acces the client, appDetails and auth directly from this function to make the references more direct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've checked also if any project was using the static version of finishUpload but seems that nothing is using it: https://github.com/search?q=org%3Ainternxt%20finishUpload&type=code.

private async finishUploadRequest(
bucketId: string,
payload: FinishUploadPayload | FinishMultipartUploadPayload,
{ client, appDetails, auth }: NetworkRequestConfig,
signal?: AbortSignal,
) {
const headers = Network.headersWithBasicAuth(appDetails, auth);
return client.post<FinishUploadResponse>(`/v2/buckets/${bucketId}/files/finish`, payload, headers);
const headers = Network.headersWithBasicAuth(this.appDetails, this.auth);
return await this.client.post<FinishUploadResponse>(
`/v2/buckets/${bucketId}/files/finish`,
payload,
headers,
signal,
);
}

/**
* Gets the download links for a file
* @param bucketId
* @param file
*/
private static getDownloadLinks(
private static async getDownloadLinks(
bucketId: string,
fileId: string,
{ client, appDetails, auth }: NetworkRequestConfig,
Expand All @@ -245,7 +207,7 @@ export class Network {
? Network.headersWithAuthToken(appDetails, token)
: Network.headersWithBasicAuth(appDetails, auth);

return client.get<GetDownloadLinksResponse>(`/buckets/${bucketId}/files/${fileId}/info`, {
return await client.get<GetDownloadLinksResponse>(`/buckets/${bucketId}/files/${fileId}/info`, {
...headers,
'x-api-version': '2',
});
Expand All @@ -256,9 +218,13 @@ export class Network {
* @param bucketId
* @param file
*/
private static deleteFile(bucketId: string, fileId: string, { client, appDetails, auth }: NetworkRequestConfig) {
private static async deleteFile(
bucketId: string,
fileId: string,
{ client, appDetails, auth }: NetworkRequestConfig,
) {
const headers = Network.headersWithBasicAuth(appDetails, auth);
return client.delete(`/v2/buckets/${bucketId}/files/${fileId}`, headers);
return await client.delete(`/v2/buckets/${bucketId}/files/${fileId}`, headers);
}

/**
Expand Down
28 changes: 6 additions & 22 deletions src/network/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export async function uploadFile(
fileSize: number,
encryptFile: EncryptFileFunction,
uploadFile: UploadFileFunction,
signal?: AbortSignal,
): Promise<string> {
let index: BinaryData;
let iv: BinaryData;
Expand All @@ -33,14 +34,7 @@ export async function uploadFile(
iv = index.slice(0, 16);
key = await crypto.generateFileKey(mnemonic, bucketId, index);

const { uploads } = await network.startUpload(bucketId, {
uploads: [
{
index: 0,
size: fileSize,
},
],
});
const { uploads } = await network.startUpload(bucketId, fileSize, signal);

const [{ url, uuid }] = uploads;

Expand All @@ -56,7 +50,7 @@ export async function uploadFile(
shards: [{ hash, uuid }],
};

const finishUploadResponse = await network.finishUpload(bucketId, finishUploadPayload);
const finishUploadResponse = await network.finishUpload(bucketId, finishUploadPayload, signal);

return finishUploadResponse.id;
} catch (err) {
Expand Down Expand Up @@ -86,6 +80,7 @@ export async function uploadMultipartFile(
fileSize: number,
encryptFile: EncryptFileFunction,
uploadMultiparts: UploadFileMultipartFunction,
signal?: AbortSignal,
parts = 1,
): Promise<string> {
const mnemonicIsValid = crypto.validateMnemonic(mnemonic);
Expand All @@ -98,18 +93,7 @@ export async function uploadMultipartFile(
const iv = index.slice(0, 16);
const key = await crypto.generateFileKey(mnemonic, bucketId, index);

const { uploads } = await network.startUpload(
bucketId,
{
uploads: [
{
index: 0,
size: fileSize,
},
],
},
parts,
);
const { uploads } = await network.startUpload(bucketId, fileSize, signal, parts);

const [{ urls, uuid, UploadId }] = uploads;

Expand All @@ -128,7 +112,7 @@ export async function uploadMultipartFile(
shards: [{ hash, uuid, UploadId, parts: uploadedPartsReference }],
};

const finishUploadResponse = await network.finishUpload(bucketId, finishUploadPayload);
const finishUploadResponse = await network.finishUpload(bucketId, finishUploadPayload, signal);

return finishUploadResponse.id;
}
32 changes: 16 additions & 16 deletions src/shared/http/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ export class HttpClient {
* @param url
* @param headers
*/
public get<Response>(url: URL, headers: Headers): Promise<Response> {
return this.execute(() => this.axios.get(url, { headers }));
public async get<Response>(url: URL, headers: Headers): Promise<Response> {
return await this.execute(() => this.axios.get(url, { headers }));
}

/**
Expand All @@ -95,8 +95,8 @@ export class HttpClient {
* @param params
* @param headers
*/
public getWithParams<Response>(url: URL, params: Parameters, headers: Headers): Promise<Response> {
return this.execute(() => this.axios.get(url, { params, headers }));
public async getWithParams<Response>(url: URL, params: Parameters, headers: Headers): Promise<Response> {
return await this.execute(() => this.axios.get(url, { params, headers }));
}

/**
Expand Down Expand Up @@ -129,8 +129,8 @@ export class HttpClient {
* @param params
* @param headers
*/
public post<Response>(url: URL, params: Parameters, headers: Headers): Promise<Response> {
return this.execute(() => this.axios.post(url, params, { headers }));
public async post<Response>(url: URL, params: Parameters, headers: Headers, signal?: AbortSignal): Promise<Response> {
return await this.execute(() => this.axios.post(url, params, { headers, signal }));
}

/**
Expand All @@ -139,8 +139,8 @@ export class HttpClient {
* @param params
* @param headers
*/
public postForm<Response>(url: URL, params: Parameters, headers: Headers): Promise<Response> {
return this.execute(() => this.axios.postForm(url, params, { headers }));
public async postForm<Response>(url: URL, params: Parameters, headers: Headers): Promise<Response> {
return await this.execute(() => this.axios.postForm(url, params, { headers }));
}

/**
Expand Down Expand Up @@ -175,8 +175,8 @@ export class HttpClient {
* @param params
* @param headers
*/
public patch<Response>(url: URL, params: Parameters, headers: Headers): Promise<Response> {
return this.execute(() => this.axios.patch(url, params, { headers }));
public async patch<Response>(url: URL, params: Parameters, headers: Headers): Promise<Response> {
return await this.execute(() => this.axios.patch(url, params, { headers }));
}

/**
Expand All @@ -185,8 +185,8 @@ export class HttpClient {
* @param params
* @param headers
*/
public put<Response>(url: URL, params: Parameters, headers: Headers): Promise<Response> {
return this.execute(() => this.axios.put(url, params, { headers }));
public async put<Response>(url: URL, params: Parameters, headers: Headers): Promise<Response> {
return await this.execute(() => this.axios.put(url, params, { headers }));
}

/**
Expand All @@ -195,8 +195,8 @@ export class HttpClient {
* @param params
* @param headers
*/
public putForm<Response>(url: URL, params: Parameters, headers: Headers): Promise<Response> {
return this.execute(() => this.axios.putForm(url, params, { headers }));
public async putForm<Response>(url: URL, params: Parameters, headers: Headers): Promise<Response> {
return await this.execute(() => this.axios.putForm(url, params, { headers }));
}

/**
Expand All @@ -205,8 +205,8 @@ export class HttpClient {
* @param headers
* @param params
*/
public delete<Response>(url: URL, headers: Headers, params?: Parameters): Promise<Response> {
return this.execute(() => this.axios.delete(url, { headers, data: params }));
public async delete<Response>(url: URL, headers: Headers, params?: Parameters): Promise<Response> {
return await this.execute(() => this.axios.delete(url, { headers, data: params }));
}

/**
Expand Down
Loading