-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.js
More file actions
106 lines (94 loc) · 2.95 KB
/
utils.js
File metadata and controls
106 lines (94 loc) · 2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/**
* Utility functions for nostr-git-client
*/
import LightningFS from '@isomorphic-git/lightning-fs';
/**
* Create a LightningFS instance for IndexedDB storage
* @param {string} name - Database name
* @returns {LightningFS} Filesystem instance
*/
export function createFS(name = 'nostr-git-client') {
return new LightningFS(name);
}
/**
* Create an HTTP client for isomorphic-git
* Works with JSS and other git HTTP servers
* @param {Object} options
* @param {string} options.corsProxy - CORS proxy URL (optional)
* @param {Object} options.headers - Additional headers
* @returns {Object} HTTP client for isomorphic-git
*/
export function createHttpClient(options = {}) {
const { corsProxy, headers = {} } = options;
return {
async request({ url, method, headers: reqHeaders, body }) {
// Apply CORS proxy if specified
const finalUrl = corsProxy ? `${corsProxy}${encodeURIComponent(url)}` : url;
// isomorphic-git may pass body as array of Uint8Arrays - concatenate them
let requestBody = body;
if (Array.isArray(body)) {
const chunks = [];
for (const chunk of body) {
chunks.push(chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk));
}
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
requestBody = new Uint8Array(totalLength);
let offset = 0;
for (const chunk of chunks) {
requestBody.set(chunk, offset);
offset += chunk.length;
}
}
const res = await fetch(finalUrl, {
method,
headers: { ...reqHeaders, ...headers },
body: requestBody
});
return {
url: res.url,
method,
statusCode: res.status,
statusMessage: res.statusText,
headers: Object.fromEntries(res.headers.entries()),
body: [new Uint8Array(await res.arrayBuffer())]
};
}
};
}
/**
* Verify Nostr event signature
* @param {Object} event - Nostr event
* @returns {boolean} True if valid
*/
export async function verifyEvent(event) {
try {
const { verifyEvent } = await import('nostr-tools/pure');
return verifyEvent(event);
} catch {
// Fallback: assume valid if nostr-tools not available
console.warn('nostr-tools not available for signature verification');
return true;
}
}
/**
* Parse a 30618 repo state event
* @param {Object} event - Nostr event
* @returns {Object|null} Parsed event data
*/
export function parseRepoEvent(event) {
if (event.kind !== 30618) return null;
const repoId = event.tags.find(t => t[0] === 'd')?.[1];
const refTag = event.tags.find(t => t[0].startsWith('refs/'));
const anchorTag = event.tags.find(t => t[0] === 'c');
if (!repoId || !refTag) return null;
return {
pubkey: event.pubkey,
repoId,
ref: refTag[0],
branch: refTag[0].replace('refs/heads/', ''),
commit: refTag[1],
anchor: anchorTag?.[1] || null,
createdAt: event.created_at,
raw: event
};
}