@net-protocol/storage 0.1.8 → 0.1.9

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.
package/dist/index.d.mts CHANGED
@@ -535,6 +535,99 @@ declare function detectFileTypeFromBase64(base64Data: string): string | undefine
535
535
  */
536
536
  declare function base64ToDataUri(base64Data: string): string;
537
537
 
538
+ /**
539
+ * Streaming utilities for processing large files without loading them entirely into memory.
540
+ * Uses file.slice() to read in chunks, keeping memory usage low.
541
+ */
542
+ /**
543
+ * Result from processing a single file chunk
544
+ */
545
+ interface StreamingChunkResult {
546
+ /** Index of this chunk (0-based) */
547
+ chunkIndex: number;
548
+ /** Keccak256 hash of the chunk content (66 chars) */
549
+ hash: string;
550
+ /** Compressed chunks ready for ChunkedStorage (array of hex strings) */
551
+ compressedChunks: string[];
552
+ }
553
+ /**
554
+ * Result from processing an entire file via streaming
555
+ */
556
+ interface StreamingProcessResult {
557
+ /** All chunk hashes in order */
558
+ hashes: string[];
559
+ /** All compressed chunk arrays in order */
560
+ allCompressedChunks: string[][];
561
+ /** Total number of chunks */
562
+ totalChunks: number;
563
+ /** Whether the file was treated as binary */
564
+ isBinary: boolean;
565
+ }
566
+ /**
567
+ * Detects if a file should be treated as binary based on its MIME type.
568
+ * Binary files will be base64 encoded; text files will be read as text.
569
+ *
570
+ * @param file - The file to check
571
+ * @returns true if the file should be treated as binary
572
+ */
573
+ declare function isBinaryFile(file: File): boolean;
574
+ /**
575
+ * Reads a slice of a file as a string.
576
+ * For binary files, returns base64-encoded data.
577
+ * For text files, returns the raw text.
578
+ *
579
+ * @param file - The file to read from
580
+ * @param offset - Start byte offset
581
+ * @param size - Number of bytes to read
582
+ * @param isBinary - Whether to read as binary (base64) or text
583
+ * @param isFirstChunk - Whether this is the first chunk (for data URI prefix)
584
+ * @returns The chunk as a string
585
+ */
586
+ declare function readFileSlice(file: File, offset: number, size: number, isBinary: boolean, isFirstChunk: boolean): Promise<string>;
587
+ /**
588
+ * Async generator that processes a file in streaming chunks.
589
+ * Reads the file in 80KB slices, hashes and compresses each,
590
+ * yielding results one at a time to keep memory usage low.
591
+ *
592
+ * @param file - The file to process
593
+ * @param chunkSize - Size of each chunk in bytes (default: 80KB)
594
+ * @yields StreamingChunkResult for each chunk processed
595
+ *
596
+ * @example
597
+ * ```typescript
598
+ * const hashes: string[] = [];
599
+ * const transactions: TransactionConfig[] = [];
600
+ *
601
+ * for await (const result of processFileStreaming(file)) {
602
+ * hashes.push(result.hash);
603
+ * transactions.push(createTransaction(result.compressedChunks));
604
+ * }
605
+ *
606
+ * const metadata = generateXmlMetadata(hashes, 0, operatorAddress);
607
+ * ```
608
+ */
609
+ declare function processFileStreaming(file: File, chunkSize?: number): AsyncGenerator<StreamingChunkResult>;
610
+ /**
611
+ * Processes an entire file via streaming and returns all results.
612
+ * This is a convenience function that collects all generator results.
613
+ *
614
+ * For very large files, prefer using processFileStreaming directly
615
+ * to process chunks as they're generated.
616
+ *
617
+ * @param file - The file to process
618
+ * @param onProgress - Optional callback for progress updates
619
+ * @returns All hashes and compressed chunks
620
+ */
621
+ declare function processFileStreamingComplete(file: File, onProgress?: (current: number, total: number) => void): Promise<StreamingProcessResult>;
622
+ /**
623
+ * Estimates the number of chunks for a file without reading it.
624
+ *
625
+ * @param fileSize - Size of the file in bytes
626
+ * @param isBinary - Whether the file is binary (uses smaller chunk size for base64 alignment)
627
+ * @returns Estimated number of chunks
628
+ */
629
+ declare function estimateChunkCount(fileSize: number, isBinary?: boolean): number;
630
+
538
631
  declare const STORAGE_CONTRACT: {
539
632
  abi: Abi;
540
633
  address: `0x${string}`;
@@ -570,4 +663,4 @@ declare const CONCURRENT_XML_FETCHES = 3;
570
663
  */
571
664
  declare function resolveXmlRecursive(content: string, defaultOperator: string, client: PublicClient, maxDepth: number, visited?: Set<string>, inheritedOperator?: string): Promise<string>;
572
665
 
573
- export { type BulkStorageKey, CHUNKED_STORAGE_CONTRACT, CHUNKED_STORAGE_READER_CONTRACT, CONCURRENT_XML_FETCHES, type ChunkedMetadata, MAX_XML_DEPTH, SAFE_STORAGE_READER_CONTRACT, STORAGE_CONTRACT, STORAGE_ROUTER_CONTRACT, StorageClient, type StorageClientOptions, type StorageData, type UseStorageOptions, type UseXmlStorageOptions, type XmlReference$1 as XmlReference, assembleChunks, base64ToDataUri, chunkData, chunkDataForStorage, computeTopLevelHash, containsXmlReferences, detectFileTypeFromBase64, detectStorageType, encodeStorageKeyForUrl, fileToDataUri, formatStorageKeyForDisplay, generateStorageEmbedTag, generateXmlMetadata, generateXmlMetadataWithSource, getChunkCount, getReferenceKey, getStorageKeyBytes, parseNetReferences, processDataForStorage, resolveOperator, resolveXmlRecursive, shouldSuggestXmlStorage, useBulkStorage, useStorage, useStorageForOperator, useStorageForOperatorAndKey, useStorageFromRouter, useStorageTotalWrites, useXmlStorage, validateDataSize };
666
+ export { type BulkStorageKey, CHUNKED_STORAGE_CONTRACT, CHUNKED_STORAGE_READER_CONTRACT, CONCURRENT_XML_FETCHES, type ChunkedMetadata, MAX_XML_DEPTH, SAFE_STORAGE_READER_CONTRACT, STORAGE_CONTRACT, STORAGE_ROUTER_CONTRACT, StorageClient, type StorageClientOptions, type StorageData, type StreamingChunkResult, type StreamingProcessResult, type UseStorageOptions, type UseXmlStorageOptions, type XmlReference$1 as XmlReference, assembleChunks, base64ToDataUri, chunkData, chunkDataForStorage, computeTopLevelHash, containsXmlReferences, detectFileTypeFromBase64, detectStorageType, encodeStorageKeyForUrl, estimateChunkCount, fileToDataUri, formatStorageKeyForDisplay, generateStorageEmbedTag, generateXmlMetadata, generateXmlMetadataWithSource, getChunkCount, getReferenceKey, getStorageKeyBytes, isBinaryFile, parseNetReferences, processDataForStorage, processFileStreaming, processFileStreamingComplete, readFileSlice, resolveOperator, resolveXmlRecursive, shouldSuggestXmlStorage, useBulkStorage, useStorage, useStorageForOperator, useStorageForOperatorAndKey, useStorageFromRouter, useStorageTotalWrites, useXmlStorage, validateDataSize };
package/dist/index.d.ts CHANGED
@@ -535,6 +535,99 @@ declare function detectFileTypeFromBase64(base64Data: string): string | undefine
535
535
  */
536
536
  declare function base64ToDataUri(base64Data: string): string;
537
537
 
538
+ /**
539
+ * Streaming utilities for processing large files without loading them entirely into memory.
540
+ * Uses file.slice() to read in chunks, keeping memory usage low.
541
+ */
542
+ /**
543
+ * Result from processing a single file chunk
544
+ */
545
+ interface StreamingChunkResult {
546
+ /** Index of this chunk (0-based) */
547
+ chunkIndex: number;
548
+ /** Keccak256 hash of the chunk content (66 chars) */
549
+ hash: string;
550
+ /** Compressed chunks ready for ChunkedStorage (array of hex strings) */
551
+ compressedChunks: string[];
552
+ }
553
+ /**
554
+ * Result from processing an entire file via streaming
555
+ */
556
+ interface StreamingProcessResult {
557
+ /** All chunk hashes in order */
558
+ hashes: string[];
559
+ /** All compressed chunk arrays in order */
560
+ allCompressedChunks: string[][];
561
+ /** Total number of chunks */
562
+ totalChunks: number;
563
+ /** Whether the file was treated as binary */
564
+ isBinary: boolean;
565
+ }
566
+ /**
567
+ * Detects if a file should be treated as binary based on its MIME type.
568
+ * Binary files will be base64 encoded; text files will be read as text.
569
+ *
570
+ * @param file - The file to check
571
+ * @returns true if the file should be treated as binary
572
+ */
573
+ declare function isBinaryFile(file: File): boolean;
574
+ /**
575
+ * Reads a slice of a file as a string.
576
+ * For binary files, returns base64-encoded data.
577
+ * For text files, returns the raw text.
578
+ *
579
+ * @param file - The file to read from
580
+ * @param offset - Start byte offset
581
+ * @param size - Number of bytes to read
582
+ * @param isBinary - Whether to read as binary (base64) or text
583
+ * @param isFirstChunk - Whether this is the first chunk (for data URI prefix)
584
+ * @returns The chunk as a string
585
+ */
586
+ declare function readFileSlice(file: File, offset: number, size: number, isBinary: boolean, isFirstChunk: boolean): Promise<string>;
587
+ /**
588
+ * Async generator that processes a file in streaming chunks.
589
+ * Reads the file in 80KB slices, hashes and compresses each,
590
+ * yielding results one at a time to keep memory usage low.
591
+ *
592
+ * @param file - The file to process
593
+ * @param chunkSize - Size of each chunk in bytes (default: 80KB)
594
+ * @yields StreamingChunkResult for each chunk processed
595
+ *
596
+ * @example
597
+ * ```typescript
598
+ * const hashes: string[] = [];
599
+ * const transactions: TransactionConfig[] = [];
600
+ *
601
+ * for await (const result of processFileStreaming(file)) {
602
+ * hashes.push(result.hash);
603
+ * transactions.push(createTransaction(result.compressedChunks));
604
+ * }
605
+ *
606
+ * const metadata = generateXmlMetadata(hashes, 0, operatorAddress);
607
+ * ```
608
+ */
609
+ declare function processFileStreaming(file: File, chunkSize?: number): AsyncGenerator<StreamingChunkResult>;
610
+ /**
611
+ * Processes an entire file via streaming and returns all results.
612
+ * This is a convenience function that collects all generator results.
613
+ *
614
+ * For very large files, prefer using processFileStreaming directly
615
+ * to process chunks as they're generated.
616
+ *
617
+ * @param file - The file to process
618
+ * @param onProgress - Optional callback for progress updates
619
+ * @returns All hashes and compressed chunks
620
+ */
621
+ declare function processFileStreamingComplete(file: File, onProgress?: (current: number, total: number) => void): Promise<StreamingProcessResult>;
622
+ /**
623
+ * Estimates the number of chunks for a file without reading it.
624
+ *
625
+ * @param fileSize - Size of the file in bytes
626
+ * @param isBinary - Whether the file is binary (uses smaller chunk size for base64 alignment)
627
+ * @returns Estimated number of chunks
628
+ */
629
+ declare function estimateChunkCount(fileSize: number, isBinary?: boolean): number;
630
+
538
631
  declare const STORAGE_CONTRACT: {
539
632
  abi: Abi;
540
633
  address: `0x${string}`;
@@ -570,4 +663,4 @@ declare const CONCURRENT_XML_FETCHES = 3;
570
663
  */
571
664
  declare function resolveXmlRecursive(content: string, defaultOperator: string, client: PublicClient, maxDepth: number, visited?: Set<string>, inheritedOperator?: string): Promise<string>;
572
665
 
573
- export { type BulkStorageKey, CHUNKED_STORAGE_CONTRACT, CHUNKED_STORAGE_READER_CONTRACT, CONCURRENT_XML_FETCHES, type ChunkedMetadata, MAX_XML_DEPTH, SAFE_STORAGE_READER_CONTRACT, STORAGE_CONTRACT, STORAGE_ROUTER_CONTRACT, StorageClient, type StorageClientOptions, type StorageData, type UseStorageOptions, type UseXmlStorageOptions, type XmlReference$1 as XmlReference, assembleChunks, base64ToDataUri, chunkData, chunkDataForStorage, computeTopLevelHash, containsXmlReferences, detectFileTypeFromBase64, detectStorageType, encodeStorageKeyForUrl, fileToDataUri, formatStorageKeyForDisplay, generateStorageEmbedTag, generateXmlMetadata, generateXmlMetadataWithSource, getChunkCount, getReferenceKey, getStorageKeyBytes, parseNetReferences, processDataForStorage, resolveOperator, resolveXmlRecursive, shouldSuggestXmlStorage, useBulkStorage, useStorage, useStorageForOperator, useStorageForOperatorAndKey, useStorageFromRouter, useStorageTotalWrites, useXmlStorage, validateDataSize };
666
+ export { type BulkStorageKey, CHUNKED_STORAGE_CONTRACT, CHUNKED_STORAGE_READER_CONTRACT, CONCURRENT_XML_FETCHES, type ChunkedMetadata, MAX_XML_DEPTH, SAFE_STORAGE_READER_CONTRACT, STORAGE_CONTRACT, STORAGE_ROUTER_CONTRACT, StorageClient, type StorageClientOptions, type StorageData, type StreamingChunkResult, type StreamingProcessResult, type UseStorageOptions, type UseXmlStorageOptions, type XmlReference$1 as XmlReference, assembleChunks, base64ToDataUri, chunkData, chunkDataForStorage, computeTopLevelHash, containsXmlReferences, detectFileTypeFromBase64, detectStorageType, encodeStorageKeyForUrl, estimateChunkCount, fileToDataUri, formatStorageKeyForDisplay, generateStorageEmbedTag, generateXmlMetadata, generateXmlMetadataWithSource, getChunkCount, getReferenceKey, getStorageKeyBytes, isBinaryFile, parseNetReferences, processDataForStorage, processFileStreaming, processFileStreamingComplete, readFileSlice, resolveOperator, resolveXmlRecursive, shouldSuggestXmlStorage, useBulkStorage, useStorage, useStorageForOperator, useStorageForOperatorAndKey, useStorageFromRouter, useStorageTotalWrites, useXmlStorage, validateDataSize };
package/dist/index.js CHANGED
@@ -2209,6 +2209,129 @@ function base64ToDataUri(base64Data) {
2209
2209
  const mimeType = detectFileTypeFromBase64(base64Data) || "application/octet-stream";
2210
2210
  return `data:${mimeType};base64,${base64Data}`;
2211
2211
  }
2212
+ var STREAMING_CHUNK_SIZE = 80 * 1e3;
2213
+ var BINARY_CHUNK_SIZE = 79998;
2214
+ function isBinaryFile(file) {
2215
+ const mimeType = file.type.toLowerCase();
2216
+ const textTypes = [
2217
+ "text/",
2218
+ "application/json",
2219
+ "application/xml",
2220
+ "application/javascript",
2221
+ "application/typescript",
2222
+ "application/x-javascript",
2223
+ "application/ecmascript"
2224
+ ];
2225
+ for (const textType of textTypes) {
2226
+ if (mimeType.startsWith(textType)) {
2227
+ return false;
2228
+ }
2229
+ }
2230
+ if (!mimeType || mimeType === "application/octet-stream") {
2231
+ const extension = file.name.split(".").pop()?.toLowerCase() || "";
2232
+ const textExtensions = [
2233
+ "txt",
2234
+ "md",
2235
+ "json",
2236
+ "xml",
2237
+ "html",
2238
+ "htm",
2239
+ "css",
2240
+ "js",
2241
+ "ts",
2242
+ "jsx",
2243
+ "tsx",
2244
+ "yaml",
2245
+ "yml",
2246
+ "toml",
2247
+ "ini",
2248
+ "cfg",
2249
+ "conf",
2250
+ "log",
2251
+ "csv",
2252
+ "svg"
2253
+ ];
2254
+ return !textExtensions.includes(extension);
2255
+ }
2256
+ return true;
2257
+ }
2258
+ async function readFileSlice(file, offset, size, isBinary, isFirstChunk) {
2259
+ const blob = file.slice(offset, offset + size);
2260
+ if (isBinary) {
2261
+ const arrayBuffer = await blob.arrayBuffer();
2262
+ const bytes = new Uint8Array(arrayBuffer);
2263
+ let base64 = "";
2264
+ const chunkSize = 32766;
2265
+ for (let i = 0; i < bytes.length; i += chunkSize) {
2266
+ const chunk = bytes.slice(i, i + chunkSize);
2267
+ base64 += btoa(String.fromCharCode(...chunk));
2268
+ }
2269
+ if (isFirstChunk) {
2270
+ const mimeType = detectFileTypeFromBase64(base64) || file.type || "application/octet-stream";
2271
+ return `data:${mimeType};base64,${base64}`;
2272
+ }
2273
+ return base64;
2274
+ } else {
2275
+ return await blob.text();
2276
+ }
2277
+ }
2278
+ async function* processFileStreaming(file, chunkSize = STREAMING_CHUNK_SIZE) {
2279
+ const binary = isBinaryFile(file);
2280
+ const effectiveChunkSize = binary ? BINARY_CHUNK_SIZE : chunkSize;
2281
+ let offset = 0;
2282
+ let chunkIndex = 0;
2283
+ while (offset < file.size) {
2284
+ const chunkString = await readFileSlice(
2285
+ file,
2286
+ offset,
2287
+ effectiveChunkSize,
2288
+ binary,
2289
+ chunkIndex === 0
2290
+ );
2291
+ const hash = core.keccak256HashString(chunkString);
2292
+ const compressedChunks = chunkDataForStorage(chunkString);
2293
+ yield {
2294
+ chunkIndex,
2295
+ hash,
2296
+ compressedChunks
2297
+ };
2298
+ offset += effectiveChunkSize;
2299
+ chunkIndex++;
2300
+ }
2301
+ if (chunkIndex === 0) {
2302
+ const emptyString = binary ? `data:${file.type || "application/octet-stream"};base64,` : "";
2303
+ const hash = core.keccak256HashString(emptyString);
2304
+ const compressedChunks = chunkDataForStorage(emptyString);
2305
+ yield {
2306
+ chunkIndex: 0,
2307
+ hash,
2308
+ compressedChunks
2309
+ };
2310
+ }
2311
+ }
2312
+ async function processFileStreamingComplete(file, onProgress) {
2313
+ const totalChunks = Math.max(1, Math.ceil(file.size / STREAMING_CHUNK_SIZE));
2314
+ const hashes = [];
2315
+ const allCompressedChunks = [];
2316
+ const binary = isBinaryFile(file);
2317
+ let processed = 0;
2318
+ for await (const result of processFileStreaming(file)) {
2319
+ hashes.push(result.hash);
2320
+ allCompressedChunks.push(result.compressedChunks);
2321
+ processed++;
2322
+ onProgress?.(processed, totalChunks);
2323
+ }
2324
+ return {
2325
+ hashes,
2326
+ allCompressedChunks,
2327
+ totalChunks: hashes.length,
2328
+ isBinary: binary
2329
+ };
2330
+ }
2331
+ function estimateChunkCount(fileSize, isBinary = true) {
2332
+ const chunkSize = isBinary ? BINARY_CHUNK_SIZE : STREAMING_CHUNK_SIZE;
2333
+ return Math.max(1, Math.ceil(fileSize / chunkSize));
2334
+ }
2212
2335
 
2213
2336
  exports.CHUNKED_STORAGE_CONTRACT = CHUNKED_STORAGE_CONTRACT;
2214
2337
  exports.CHUNKED_STORAGE_READER_CONTRACT = CHUNKED_STORAGE_READER_CONTRACT;
@@ -2227,6 +2350,7 @@ exports.containsXmlReferences = containsXmlReferences;
2227
2350
  exports.detectFileTypeFromBase64 = detectFileTypeFromBase64;
2228
2351
  exports.detectStorageType = detectStorageType;
2229
2352
  exports.encodeStorageKeyForUrl = encodeStorageKeyForUrl;
2353
+ exports.estimateChunkCount = estimateChunkCount;
2230
2354
  exports.fileToDataUri = fileToDataUri;
2231
2355
  exports.formatStorageKeyForDisplay = formatStorageKeyForDisplay;
2232
2356
  exports.generateStorageEmbedTag = generateStorageEmbedTag;
@@ -2235,8 +2359,12 @@ exports.generateXmlMetadataWithSource = generateXmlMetadataWithSource;
2235
2359
  exports.getChunkCount = getChunkCount;
2236
2360
  exports.getReferenceKey = getReferenceKey;
2237
2361
  exports.getStorageKeyBytes = getStorageKeyBytes;
2362
+ exports.isBinaryFile = isBinaryFile;
2238
2363
  exports.parseNetReferences = parseNetReferences;
2239
2364
  exports.processDataForStorage = processDataForStorage;
2365
+ exports.processFileStreaming = processFileStreaming;
2366
+ exports.processFileStreamingComplete = processFileStreamingComplete;
2367
+ exports.readFileSlice = readFileSlice;
2240
2368
  exports.resolveOperator = resolveOperator;
2241
2369
  exports.resolveXmlRecursive = resolveXmlRecursive;
2242
2370
  exports.shouldSuggestXmlStorage = shouldSuggestXmlStorage;