most-box 0.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,141 @@
1
+ /**
2
+ * CID (Content Identifier) Calculation Module
3
+ * Handles IPFS UnixFS CID computation for files
4
+ */
5
+
6
+ import fs from 'node:fs'
7
+ import { Readable } from 'node:stream'
8
+ import { importer } from 'ipfs-unixfs-importer'
9
+
10
+ /**
11
+ * Dummy Blockstore for CID calculation
12
+ * Does not store any data, only used for streaming CID computation
13
+ */
14
+ function createDummyBlockstore() {
15
+ return {
16
+ put: async (key, val) => key,
17
+ get: async () => { throw new Error('Not implemented') },
18
+ has: async () => false
19
+ }
20
+ }
21
+
22
+ /**
23
+ * Calculate IPFS UnixFS CID v1 for content
24
+ * Uses streaming approach to handle large files efficiently
25
+ *
26
+ * @param {string|Buffer|AsyncIterable} content - File path (string), Buffer, or async iterable
27
+ * @param {object} options - Calculation options
28
+ * @param {boolean} [options.rawLeaves=true] - Use raw leaves for modern CID
29
+ * @param {number} [options.cidVersion=1] - CID version (0 or 1)
30
+ * @param {number} [options.size] - Total size in bytes (optional, auto-detected for files)
31
+ * @returns {Promise<{cid: import('multiformats/cid').CID, size: number}>}
32
+ */
33
+ export async function calculateCid(content, options = {}) {
34
+ const {
35
+ rawLeaves = true,
36
+ cidVersion = 1,
37
+ size: providedSize
38
+ } = options
39
+
40
+ const blockstore = createDummyBlockstore()
41
+
42
+ let rootCid = null
43
+ let totalSize = providedSize || 0
44
+
45
+ let source
46
+
47
+ if (typeof content === 'string') {
48
+ const filePath = content
49
+ try {
50
+ const stat = await fs.promises.stat(filePath)
51
+ totalSize = stat.size
52
+ } catch {
53
+ // Ignore stat errors, size will be 0
54
+ }
55
+ source = [{
56
+ path: 'file',
57
+ content: fs.createReadStream(filePath)
58
+ }]
59
+ } else if (Buffer.isBuffer(content)) {
60
+ totalSize = content.length
61
+ source = [{
62
+ path: 'file',
63
+ content: Readable.from(content)
64
+ }]
65
+ } else {
66
+ source = [{
67
+ path: 'file',
68
+ content
69
+ }]
70
+ }
71
+
72
+ try {
73
+ for await (const entry of importer(source, blockstore, {
74
+ cidVersion,
75
+ rawLeaves,
76
+ wrapWithDirectory: false
77
+ })) {
78
+ rootCid = entry.cid
79
+ }
80
+ } catch (err) {
81
+ throw new Error(`Failed to calculate CID: ${err.message}`)
82
+ }
83
+
84
+ if (!rootCid) {
85
+ throw new Error('Failed to calculate CID: no root CID generated')
86
+ }
87
+
88
+ return {
89
+ cid: rootCid,
90
+ size: totalSize
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Validate a CID string
96
+ * @param {string} cidString - CID string to validate
97
+ * @returns {{ valid: boolean, error?: string }}
98
+ */
99
+ export function validateCidString(cidString) {
100
+ if (!cidString || typeof cidString !== 'string') {
101
+ return { valid: false, error: 'CID must be a non-empty string' }
102
+ }
103
+
104
+ if (!cidString.startsWith('b')) {
105
+ return { valid: false, error: 'Invalid CID format: CID v1 must start with "b"' }
106
+ }
107
+
108
+ return { valid: true }
109
+ }
110
+
111
+ /**
112
+ * Parse a most:// link and extract the CID
113
+ * @param {string} link - most://<cid> format link
114
+ * @returns {{ cid: string, error?: string }}
115
+ */
116
+ export function parseMostLink(link) {
117
+ if (!link || typeof link !== 'string') {
118
+ return { cid: '', error: 'Link must be a non-empty string' }
119
+ }
120
+
121
+ let cidString = link
122
+
123
+ if (link.startsWith('most://')) {
124
+ cidString = link.replace('most://', '')
125
+ }
126
+
127
+ // Remove any trailing slashes or whitespace
128
+ cidString = cidString.trim().replace(/\/+$/, '')
129
+
130
+ // Handle URL-like parsing for potential extra paths
131
+ if (cidString.includes('/')) {
132
+ cidString = cidString.split('/')[0]
133
+ }
134
+
135
+ const validation = validateCidString(cidString)
136
+ if (!validation.valid) {
137
+ return { cid: '', error: validation.error }
138
+ }
139
+
140
+ return { cid: cidString }
141
+ }