portal-dashboard/app/data/file-provider.ts

135 lines
3.8 KiB
TypeScript
Raw Normal View History

import type {SdkProvider} from "~/data/sdk-provider.js";
import type {S5Client} from "@lumeweb/s5-js";
2024-03-21 17:24:13 +00:00
import {PROTOCOL_S5} from "@lumeweb/portal-sdk";
import {Multihash} from "@lumeweb/libs5/lib/multihash.js";
import type {AxiosProgressEvent} from "axios";
2024-03-21 20:45:06 +00:00
import {CID, CID_TYPES, METADATA_TYPES, metadataMagicByte, Unpacker} from "@lumeweb/libs5";
2024-03-21 17:24:13 +00:00
async function getIsManifest(s5: S5Client, hash: string): Promise<boolean | number> {
let type: number | null;
try {
2024-03-21 20:15:04 +00:00
const abort = new AbortController();
2024-03-21 17:24:13 +00:00
const resp = s5.downloadData(hash, {
onDownloadProgress: (progressEvent: AxiosProgressEvent) => {
if (progressEvent.loaded >= 10) {
2024-03-21 20:15:04 +00:00
abort.abort();
2024-03-21 17:24:13 +00:00
}
},
2024-03-21 20:15:04 +00:00
httpConfig: {
signal: abort.signal,
},
});
2024-03-21 17:24:13 +00:00
const data = await resp;
const unpacker = Unpacker.fromPacked(Buffer.from(data));
try {
const magic = unpacker.unpackInt();
if (magic !== metadataMagicByte) {
return false;
}
type = unpacker.unpackInt();
if (!type || !Object.values(METADATA_TYPES).includes(type)) {
return false;
}
} catch (e) {
return false;
}
} catch (e) {
return false;
2024-03-21 05:15:12 +00:00
}
2024-03-21 17:24:13 +00:00
switch (type) {
case METADATA_TYPES.DIRECTORY:
return CID_TYPES.DIRECTORY;
case METADATA_TYPES.WEBAPP:
return CID_TYPES.METADATA_WEBAPP;
case METADATA_TYPES.MEDIA:
return CID_TYPES.METADATA_MEDIA;
case METADATA_TYPES.USER_IDENTITY:
return CID_TYPES.USER_IDENTITY;
}
return 0;
}
export interface FileItem {
cid: string;
type: string;
2024-03-21 20:49:14 +00:00
size: number;
2024-03-21 17:24:13 +00:00
mimeType: string;
2024-03-21 20:45:06 +00:00
pinned: string;
2024-03-21 17:24:13 +00:00
}
export const fileProvider: SdkProvider = {
sdk: undefined,
async getList() {
const items: FileItem[] = [];
try {
const s5 = fileProvider.sdk?.protocols().get<S5Client>(PROTOCOL_S5)!.getSdk()!;
const pinList = await s5.accountPins();
for (const pin of pinList!.pins) {
const manifest = await getIsManifest(s5, pin.hash) as number;
if (manifest) {
const mHash = Multihash.fromBase64Url(pin.hash);
2024-03-21 17:24:13 +00:00
items.push({
cid: new CID(manifest, mHash, pin.size).toString(),
2024-03-21 17:24:13 +00:00
type: "manifest",
mimeType: "application/octet-stream",
2024-03-21 20:49:14 +00:00
size: pin.size,
2024-03-21 20:45:06 +00:00
pinned: pin.pinned_at,
2024-03-21 17:24:13 +00:00
});
} else {
items.push({
cid: new CID(CID_TYPES.RAW, Multihash.fromBase64Url(pin.hash), pin.size).toString(),
2024-03-21 17:24:13 +00:00
type: "raw",
mimeType: pin.mime_type,
2024-03-21 20:49:14 +00:00
size: pin.size,
2024-03-21 20:45:06 +00:00
pinned: pin.pinned_at,
2024-03-21 17:24:13 +00:00
});
}
}
} catch (e) {
return Promise.reject(e);
}
return {
data: items,
total: items.length,
};
},
getOne() {
console.log("Not implemented");
return Promise.resolve({
data: {
id: 1
},
});
},
update() {
console.log("Not implemented");
return Promise.resolve({
data: {},
});
},
create() {
console.log("Not implemented");
return Promise.resolve({
data: {},
});
},
deleteOne() {
console.log("Not implemented");
return Promise.resolve({
data: {},
});
},
getApiUrl() {
return "";
},
} satisfies SdkProvider;