2024-08-15 12:08:51 +02:00
|
|
|
import { Api } from "../api/config";
|
2024-09-27 17:35:50 +02:00
|
|
|
import { CodexError } from "../errors/errors";
|
2024-08-15 12:08:51 +02:00
|
|
|
import { Fetch } from "../fetch-safe/fetch-safe";
|
|
|
|
|
import type { SafeValue } from "../values/values";
|
2024-08-30 12:24:00 +02:00
|
|
|
import type {
|
|
|
|
|
CodexDataResponse,
|
|
|
|
|
CodexNodeSpace,
|
|
|
|
|
UploadResponse,
|
|
|
|
|
} from "./types";
|
2024-08-15 12:08:51 +02:00
|
|
|
|
2024-08-29 19:41:28 +02:00
|
|
|
export class CodexData {
|
2024-08-15 12:08:51 +02:00
|
|
|
readonly url: string;
|
|
|
|
|
|
|
|
|
|
constructor(url: string) {
|
|
|
|
|
this.url = url;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Lists manifest CIDs stored locally in node.
|
|
|
|
|
* TODO: remove the faker data part when the api is ready
|
|
|
|
|
*/
|
|
|
|
|
cids(): Promise<SafeValue<CodexDataResponse>> {
|
|
|
|
|
const url = this.url + Api.config.prefix + "/data";
|
|
|
|
|
|
|
|
|
|
return Fetch.safeJson<CodexDataResponse>(url, {
|
|
|
|
|
method: "GET",
|
|
|
|
|
}).then((data) => {
|
|
|
|
|
if (data.error) {
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
error: false,
|
|
|
|
|
data: {
|
2024-08-29 19:41:28 +02:00
|
|
|
content: data.data.content,
|
2024-08-15 12:08:51 +02:00
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets a summary of the storage space allocation of the node.
|
|
|
|
|
*/
|
|
|
|
|
space() {
|
|
|
|
|
const url = this.url + Api.config.prefix + "/space";
|
|
|
|
|
|
|
|
|
|
return Fetch.safeJson<CodexNodeSpace>(url, {
|
|
|
|
|
method: "GET",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Upload a file in a streaming manner.
|
|
|
|
|
* Once completed, the file is stored in the node and can be retrieved by any node in the network using the returned CID.
|
|
|
|
|
* XMLHttpRequest is used instead of fetch for this case, to obtain progress information.
|
|
|
|
|
* A callback onProgress can be passed to receive upload progress data information.
|
|
|
|
|
*/
|
2024-09-26 17:04:04 +02:00
|
|
|
upload(
|
2024-08-15 12:08:51 +02:00
|
|
|
file: File,
|
|
|
|
|
onProgress?: (loaded: number, total: number) => void
|
2024-09-26 17:04:04 +02:00
|
|
|
): UploadResponse {
|
2024-08-15 12:08:51 +02:00
|
|
|
const url = this.url + Api.config.prefix + "/data";
|
|
|
|
|
|
|
|
|
|
const xhr = new XMLHttpRequest();
|
|
|
|
|
|
|
|
|
|
const promise = new Promise<SafeValue<string>>(async (resolve) => {
|
|
|
|
|
xhr.upload.onprogress = (evt) => {
|
|
|
|
|
if (evt.lengthComputable) {
|
|
|
|
|
onProgress?.(evt.loaded, evt.total);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
xhr.open("POST", url, true);
|
|
|
|
|
|
2024-08-15 12:08:54 +02:00
|
|
|
xhr.send(file);
|
2024-08-15 12:08:51 +02:00
|
|
|
|
|
|
|
|
xhr.onload = function () {
|
|
|
|
|
if (xhr.status != 200) {
|
|
|
|
|
resolve({
|
|
|
|
|
error: true,
|
2024-09-27 17:35:50 +02:00
|
|
|
data: new CodexError(xhr.responseText, {
|
2024-08-15 12:08:51 +02:00
|
|
|
code: xhr.status,
|
2024-09-27 17:35:50 +02:00
|
|
|
}),
|
2024-08-15 12:08:51 +02:00
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
resolve({ error: false, data: xhr.response });
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
xhr.onerror = function () {
|
|
|
|
|
resolve({
|
|
|
|
|
error: true,
|
2024-09-27 17:35:50 +02:00
|
|
|
data: new CodexError("Something went wrong during the file upload."),
|
2024-08-15 12:08:51 +02:00
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
result: promise,
|
|
|
|
|
abort: () => {
|
|
|
|
|
xhr.abort();
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Download a file from the local node in a streaming manner.
|
|
|
|
|
* If the file is not available locally, a 404 is returned.
|
|
|
|
|
* There result is a readable stream.
|
|
|
|
|
*/
|
|
|
|
|
async localDownload(cid: string) {
|
|
|
|
|
const url = this.url + Api.config.prefix + "/data/" + cid;
|
|
|
|
|
|
|
|
|
|
const res = await Fetch.safe(url, {
|
|
|
|
|
method: "GET",
|
|
|
|
|
headers: {
|
|
|
|
|
"content-type": "application/octet-stream",
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (res.error) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res.data.body;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Download a file from the network in a streaming manner.
|
|
|
|
|
* If the file is not available locally, it will be retrieved from other nodes in the network if able.
|
|
|
|
|
*/
|
|
|
|
|
async networkDownload(cid: string) {
|
|
|
|
|
const url = this.url + Api.config.prefix + `/data/${cid}/network`;
|
|
|
|
|
|
|
|
|
|
const res = await Fetch.safe(url, {
|
|
|
|
|
method: "GET",
|
|
|
|
|
headers: {
|
|
|
|
|
"content-type": "application/octet-stream",
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (res.error) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res.data.body;
|
|
|
|
|
}
|
|
|
|
|
}
|