@gethashd/bytecave-browser 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,160 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+
5
+ // src/protocol-handler.ts
6
+ function parseHashdUrl(url) {
7
+ if (!url.startsWith("hashd://")) {
8
+ throw new Error(`Invalid hashd:// URL: ${url}`);
9
+ }
10
+ const withoutProtocol = url.slice(8);
11
+ const [cid, queryString] = withoutProtocol.split("?");
12
+ if (!cid || cid.length === 0) {
13
+ throw new Error(`Invalid hashd:// URL: missing CID`);
14
+ }
15
+ const result = {
16
+ protocol: "hashd:",
17
+ cid,
18
+ raw: url
19
+ };
20
+ if (queryString) {
21
+ const params = new URLSearchParams(queryString);
22
+ if (params.has("type")) {
23
+ result.mimeType = params.get("type");
24
+ }
25
+ if (params.has("decrypt")) {
26
+ result.decrypt = params.get("decrypt") === "true";
27
+ }
28
+ }
29
+ return result;
30
+ }
31
+ function createHashdUrl(cid, options) {
32
+ let url = `hashd://${cid}`;
33
+ if (options) {
34
+ const params = new URLSearchParams();
35
+ if (options.mimeType) {
36
+ params.set("type", options.mimeType);
37
+ }
38
+ if (options.decrypt !== void 0) {
39
+ params.set("decrypt", String(options.decrypt));
40
+ }
41
+ const queryString = params.toString();
42
+ if (queryString) {
43
+ url += `?${queryString}`;
44
+ }
45
+ }
46
+ return url;
47
+ }
48
+ var BlobUrlCache = class {
49
+ constructor() {
50
+ this.cache = /* @__PURE__ */ new Map();
51
+ this.maxAge = 60 * 60 * 1e3;
52
+ }
53
+ // 1 hour
54
+ set(cid, blobUrl, mimeType) {
55
+ this.cache.set(cid, { blobUrl, mimeType, timestamp: Date.now() });
56
+ }
57
+ get(cid) {
58
+ const entry = this.cache.get(cid);
59
+ if (!entry) {
60
+ return null;
61
+ }
62
+ if (Date.now() - entry.timestamp > this.maxAge) {
63
+ this.revoke(cid);
64
+ return null;
65
+ }
66
+ return { blobUrl: entry.blobUrl, mimeType: entry.mimeType };
67
+ }
68
+ revoke(cid) {
69
+ const entry = this.cache.get(cid);
70
+ if (entry) {
71
+ URL.revokeObjectURL(entry.blobUrl);
72
+ this.cache.delete(cid);
73
+ }
74
+ }
75
+ clear() {
76
+ for (const entry of this.cache.values()) {
77
+ URL.revokeObjectURL(entry.blobUrl);
78
+ }
79
+ this.cache.clear();
80
+ }
81
+ size() {
82
+ return this.cache.size;
83
+ }
84
+ };
85
+ var blobCache = new BlobUrlCache();
86
+ function detectMimeType(data) {
87
+ if (data.length < 4) {
88
+ return "application/octet-stream";
89
+ }
90
+ if (data[0] === 137 && data[1] === 80 && data[2] === 78 && data[3] === 71) {
91
+ return "image/png";
92
+ }
93
+ if (data[0] === 255 && data[1] === 216 && data[2] === 255) {
94
+ return "image/jpeg";
95
+ }
96
+ if (data[0] === 71 && data[1] === 73 && data[2] === 70) {
97
+ return "image/gif";
98
+ }
99
+ if (data[0] === 82 && data[1] === 73 && data[2] === 70 && data[3] === 70 && data[8] === 87 && data[9] === 69 && data[10] === 66 && data[11] === 80) {
100
+ return "image/webp";
101
+ }
102
+ if (data.length >= 12 && data[4] === 102 && data[5] === 116 && data[6] === 121 && data[7] === 112) {
103
+ return "video/mp4";
104
+ }
105
+ return "application/octet-stream";
106
+ }
107
+ async function fetchHashdContent(url, client, options) {
108
+ const parsed = typeof url === "string" ? parseHashdUrl(url) : url;
109
+ const cached = blobCache.get(parsed.cid);
110
+ if (cached) {
111
+ console.log(`[HashD] Cache hit for CID: ${parsed.cid.slice(0, 16)}...`);
112
+ return {
113
+ data: new Uint8Array(),
114
+ // Don't return data for cached items
115
+ mimeType: cached.mimeType,
116
+ blobUrl: cached.blobUrl,
117
+ cached: true
118
+ };
119
+ }
120
+ console.log(`[HashD] Fetching CID: ${parsed.cid.slice(0, 16)}...`);
121
+ const result = await client.retrieve(parsed.cid);
122
+ if (!result.success || !result.data) {
123
+ throw new Error(result.error || "Failed to retrieve content");
124
+ }
125
+ const mimeType = parsed.mimeType || detectMimeType(result.data);
126
+ const dataCopy = new Uint8Array(result.data);
127
+ const blob = new Blob([dataCopy], { type: mimeType });
128
+ const blobUrl = URL.createObjectURL(blob);
129
+ blobCache.set(parsed.cid, blobUrl, mimeType);
130
+ console.log(`[HashD] Retrieved and cached CID: ${parsed.cid.slice(0, 16)}... (${mimeType})`);
131
+ return {
132
+ data: result.data,
133
+ mimeType,
134
+ blobUrl,
135
+ cached: false
136
+ };
137
+ }
138
+ async function prefetchHashdContent(url, client) {
139
+ await fetchHashdContent(url, client);
140
+ }
141
+ function clearHashdCache() {
142
+ blobCache.clear();
143
+ }
144
+ function getHashdCacheStats() {
145
+ return { size: blobCache.size() };
146
+ }
147
+ function revokeHashdUrl(cid) {
148
+ blobCache.revoke(cid);
149
+ }
150
+
151
+ export {
152
+ __publicField,
153
+ parseHashdUrl,
154
+ createHashdUrl,
155
+ fetchHashdContent,
156
+ prefetchHashdContent,
157
+ clearHashdCache,
158
+ getHashdCacheStats,
159
+ revokeHashdUrl
160
+ };