feat: SIWE auth, auto-pin, pin search/share, explorer improvements
- SIWE server-side auth (siwe + jose JWT) - Wallet provider fallback (MAOS -> MetaMask) - Auto-pin after upload (quick + crypto) - Pin search/filter in explorer - Share button (gateway link) per pin - Copy CID button per pin - Breadcrumb root navigation fix - Hydration mismatch fix (mounted state) - Defensive truncateCid for empty values - CSP fix (template literal) - Error boundaries (upload, profile, usage) - 191 tests passing
This commit is contained in:
+52
-1
@@ -9,8 +9,59 @@ export interface IPFSEntry {
|
||||
hash: string;
|
||||
}
|
||||
|
||||
/** Raw Kubo API /api/v0/ls response */
|
||||
interface KuboLink {
|
||||
Name: string;
|
||||
Type: number; // 1 = directory, 2 = file
|
||||
Size: number;
|
||||
Hash: string;
|
||||
}
|
||||
|
||||
interface KuboObject {
|
||||
Hash: string;
|
||||
Links: KuboLink[];
|
||||
}
|
||||
|
||||
interface KuboLsResponse {
|
||||
Objects: KuboObject[];
|
||||
}
|
||||
|
||||
/** Transform Kubo response to IPFSEntry[] */
|
||||
function parseKuboLs(raw: unknown): IPFSEntry[] {
|
||||
// Already an array — return as-is
|
||||
if (Array.isArray(raw)) {
|
||||
return raw as IPFSEntry[];
|
||||
}
|
||||
|
||||
// Kubo format: { Objects: [{ Links: [...] }] }
|
||||
const data = raw as KuboLsResponse;
|
||||
if (data?.Objects?.[0]?.Links) {
|
||||
return data.Objects[0].Links.map((link) => ({
|
||||
name: link.Name,
|
||||
type: link.Type === 1 ? 'dir' as const : 'file' as const,
|
||||
size: link.Size,
|
||||
hash: link.Hash,
|
||||
}));
|
||||
}
|
||||
|
||||
// Single file — Kubo wraps it in Objects but no Links
|
||||
if (data?.Objects?.[0]?.Hash) {
|
||||
const obj = data.Objects[0];
|
||||
return [{
|
||||
name: obj.Hash.slice(0, 12) + '…',
|
||||
type: 'file',
|
||||
size: 0,
|
||||
hash: obj.Hash,
|
||||
}];
|
||||
}
|
||||
|
||||
// Empty or unrecognizable response
|
||||
return [];
|
||||
}
|
||||
|
||||
export async function explorerLs(cid: string): Promise<IPFSEntry[]> {
|
||||
return apiFetch(`/explorer/ls/${encodeURIComponent(cid)}`, { method: 'POST' });
|
||||
const raw = await apiFetch<unknown>(`/explorer/ls/${encodeURIComponent(cid)}`, { method: 'POST' });
|
||||
return parseKuboLs(raw);
|
||||
}
|
||||
|
||||
export async function explorerCat(cid: string): Promise<string> {
|
||||
|
||||
Reference in New Issue
Block a user