@seedprotocol/sdk 0.2.42 → 0.2.44

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.
Files changed (139) hide show
  1. package/dist/{ArweaveClient-BXD_aTsx.js → ArweaveClient-CA1Vsnow.js} +2 -2
  2. package/dist/{ArweaveClient-BXD_aTsx.js.map → ArweaveClient-CA1Vsnow.js.map} +1 -1
  3. package/dist/{ArweaveClient-CkcZD_QE.js → ArweaveClient-MgJXScYG.js} +2 -2
  4. package/dist/{ArweaveClient-CkcZD_QE.js.map → ArweaveClient-MgJXScYG.js.map} +1 -1
  5. package/dist/{Db-DFKHN8CX.js → Db-BEoczaGe.js} +156 -165
  6. package/dist/{Db-DFKHN8CX.js.map → Db-BEoczaGe.js.map} +1 -1
  7. package/dist/{Db-LQf3Azt5.js → Db-Y1GWsyNL.js} +34 -43
  8. package/dist/{Db-LQf3Azt5.js.map → Db-Y1GWsyNL.js.map} +1 -1
  9. package/dist/{EasClient-BNwSwDTO.js → EasClient-BjlbuffX.js} +2 -2
  10. package/dist/{EasClient-BNwSwDTO.js.map → EasClient-BjlbuffX.js.map} +1 -1
  11. package/dist/{EasClient-epqE9aWI.js → EasClient-Cg1q8lBu.js} +2 -2
  12. package/dist/{EasClient-epqE9aWI.js.map → EasClient-Cg1q8lBu.js.map} +1 -1
  13. package/dist/FileManager-D53H3aUS.js +781 -0
  14. package/dist/FileManager-D53H3aUS.js.map +1 -0
  15. package/dist/FileManager-t4zcT3NL.js +38 -0
  16. package/dist/FileManager-t4zcT3NL.js.map +1 -0
  17. package/dist/{Item-BixSOZAD.js → Item-BleJyiA2.js} +9 -12
  18. package/dist/{Item-BixSOZAD.js.map → Item-BleJyiA2.js.map} +1 -1
  19. package/dist/{ItemProperty-DpGkb0Zb.js → ItemProperty-CH7JmVg-.js} +9 -12
  20. package/dist/{ItemProperty-DpGkb0Zb.js.map → ItemProperty-CH7JmVg-.js.map} +1 -1
  21. package/dist/{QueryClient-Do0C7Jnt.js → QueryClient-BKjgZnSt.js} +2 -2
  22. package/dist/{QueryClient-Do0C7Jnt.js.map → QueryClient-BKjgZnSt.js.map} +1 -1
  23. package/dist/{QueryClient-Ckl99FYC.js → QueryClient-CDsEencG.js} +2 -2
  24. package/dist/{QueryClient-Ckl99FYC.js.map → QueryClient-CDsEencG.js.map} +1 -1
  25. package/dist/bin.js +28 -27
  26. package/dist/bin.js.map +1 -1
  27. package/dist/{constants-BakHTrB9.js → constants-BIdH8wc3.js} +66 -41
  28. package/dist/constants-BIdH8wc3.js.map +1 -0
  29. package/dist/{index-sqKT92c8.js → index-DanGFTTF.js} +1263 -1539
  30. package/dist/index-DanGFTTF.js.map +1 -0
  31. package/dist/{index-DV2gvrCh.js → index-Dk6K4W4n.js} +9 -12
  32. package/dist/index-Dk6K4W4n.js.map +1 -0
  33. package/dist/main.js +7 -10
  34. package/dist/main.js.map +1 -1
  35. package/dist/node/codegen/templates/index.njk +0 -4
  36. package/dist/{seed.schema.config-Ct1bu0Yc.js → seed.schema.config-DdCq87m_.js} +9 -11
  37. package/dist/seed.schema.config-DdCq87m_.js.map +1 -0
  38. package/dist/seedSchema/index.ts +0 -2
  39. package/dist/src/BaseFileManager.ts +22 -2
  40. package/dist/src/BaseItem.ts +4 -3
  41. package/dist/src/BaseItemProperty.ts +2 -2
  42. package/dist/src/FileDownloader.ts +63 -0
  43. package/dist/src/FileManager.ts +37 -6
  44. package/dist/src/ImageResizer.ts +84 -0
  45. package/dist/src/analyzeInput.ts +22 -2
  46. package/dist/src/constants.ts +67 -60
  47. package/dist/src/createMetadata.ts +27 -2
  48. package/dist/src/download.ts +45 -202
  49. package/dist/src/filesDownload.ts +326 -0
  50. package/dist/src/getItem.ts +5 -0
  51. package/dist/src/getPublishPayload.ts +15 -8
  52. package/dist/src/helpers.ts +0 -14
  53. package/dist/src/imageResize.ts +507 -0
  54. package/dist/src/model.ts +6 -5
  55. package/dist/src/saveImageSrc.ts +15 -1
  56. package/dist/src/syncDbWithEas.ts +0 -90
  57. package/dist/src/updateItemPropertyValue.ts +16 -3
  58. package/dist/types/src/Item/BaseItem.d.ts +2 -2
  59. package/dist/types/src/Item/BaseItem.d.ts.map +1 -1
  60. package/dist/types/src/ItemProperty/BaseItemProperty.d.ts +2 -2
  61. package/dist/types/src/ItemProperty/BaseItemProperty.d.ts.map +1 -1
  62. package/dist/types/src/ItemProperty/service/actors/saveValueToDb/analyzeInput.d.ts.map +1 -1
  63. package/dist/types/src/ItemProperty/service/actors/saveValueToDb/saveImageSrc.d.ts.map +1 -1
  64. package/dist/types/src/browser/helpers/FileManager.d.ts +5 -1
  65. package/dist/types/src/browser/helpers/FileManager.d.ts.map +1 -1
  66. package/dist/types/src/browser/workers/FileDownloader.d.ts +8 -0
  67. package/dist/types/src/browser/workers/FileDownloader.d.ts.map +1 -0
  68. package/dist/types/src/browser/workers/ImageResizer.d.ts +9 -0
  69. package/dist/types/src/browser/workers/ImageResizer.d.ts.map +1 -0
  70. package/dist/types/src/browser/workers/content-hash.d.ts.map +1 -0
  71. package/dist/types/src/browser/workers/filesDownload.d.ts +3 -0
  72. package/dist/types/src/browser/workers/filesDownload.d.ts.map +1 -0
  73. package/dist/types/src/browser/workers/imageResize.d.ts +3 -0
  74. package/dist/types/src/browser/workers/imageResize.d.ts.map +1 -0
  75. package/dist/types/src/db/read/getItem.d.ts.map +1 -1
  76. package/dist/types/src/db/read/getPublishPayload.d.ts.map +1 -1
  77. package/dist/types/src/db/write/createMetadata.d.ts.map +1 -1
  78. package/dist/types/src/db/write/updateItemPropertyValue.d.ts +5 -1
  79. package/dist/types/src/db/write/updateItemPropertyValue.d.ts.map +1 -1
  80. package/dist/types/src/events/files/download.d.ts.map +1 -1
  81. package/dist/types/src/events/files/index.d.ts.map +1 -1
  82. package/dist/types/src/events/item/syncDbWithEas.d.ts.map +1 -1
  83. package/dist/types/src/helpers/FileManager/BaseFileManager.d.ts +4 -0
  84. package/dist/types/src/helpers/FileManager/BaseFileManager.d.ts.map +1 -1
  85. package/dist/types/src/helpers/constants.d.ts +7 -0
  86. package/dist/types/src/helpers/constants.d.ts.map +1 -1
  87. package/dist/types/src/helpers/files.d.ts +1 -1
  88. package/dist/types/src/helpers/files.d.ts.map +1 -1
  89. package/dist/types/src/node/helpers/FileManager.d.ts +5 -0
  90. package/dist/types/src/node/helpers/FileManager.d.ts.map +1 -1
  91. package/dist/types/src/schema/model/index.d.ts +2 -2
  92. package/dist/types/src/schema/model/index.d.ts.map +1 -1
  93. package/dist/types/src/seedSchema/index.d.ts +0 -2
  94. package/dist/types/src/seedSchema/index.d.ts.map +1 -1
  95. package/dist/types/src/services/allItems/actors/initialize.d.ts.map +1 -1
  96. package/dist/types/src/services/internal/constants.d.ts +2 -2
  97. package/dist/types/src/services/internal/constants.d.ts.map +1 -1
  98. package/dist/types/src/services/internal/helpers.d.ts.map +1 -1
  99. package/dist/types/src/types/fileManager.d.ts +15 -0
  100. package/dist/types/src/types/fileManager.d.ts.map +1 -0
  101. package/dist/types/src/types/model.d.ts +6 -5
  102. package/dist/types/src/types/model.d.ts.map +1 -1
  103. package/package.json +5 -3
  104. package/dist/FileManager-CXk83EW5.js +0 -16
  105. package/dist/FileManager-CXk83EW5.js.map +0 -1
  106. package/dist/FileManager-DXi-X7r5.js +0 -28
  107. package/dist/FileManager-DXi-X7r5.js.map +0 -1
  108. package/dist/constants-BakHTrB9.js.map +0 -1
  109. package/dist/content-hash.js +0 -27
  110. package/dist/content-hash.js.map +0 -1
  111. package/dist/index-DV2gvrCh.js.map +0 -1
  112. package/dist/index-sqKT92c8.js.map +0 -1
  113. package/dist/seed.schema.config-Ct1bu0Yc.js.map +0 -1
  114. package/dist/types/__tests__/__mocks__/browser/project/schema.d.ts +0 -52
  115. package/dist/types/__tests__/__mocks__/browser/project/schema.d.ts.map +0 -1
  116. package/dist/types/__tests__/__mocks__/node/schema.d.ts +0 -52
  117. package/dist/types/__tests__/__mocks__/node/schema.d.ts.map +0 -1
  118. package/dist/types/__tests__/browser/db/drizzle.test.d.ts +0 -2
  119. package/dist/types/__tests__/browser/db/drizzle.test.d.ts.map +0 -1
  120. package/dist/types/__tests__/browser/property/propertyMachine.test.d.ts +0 -2
  121. package/dist/types/__tests__/browser/property/propertyMachine.test.d.ts.map +0 -1
  122. package/dist/types/__tests__/browser/react/index.test.d.ts +0 -2
  123. package/dist/types/__tests__/browser/react/index.test.d.ts.map +0 -1
  124. package/dist/types/__tests__/dist/exports.test.d.ts +0 -2
  125. package/dist/types/__tests__/dist/exports.test.d.ts.map +0 -1
  126. package/dist/types/__tests__/fs/index.test.d.ts +0 -2
  127. package/dist/types/__tests__/fs/index.test.d.ts.map +0 -1
  128. package/dist/types/__tests__/index.test.d.ts +0 -2
  129. package/dist/types/__tests__/index.test.d.ts.map +0 -1
  130. package/dist/types/__tests__/node/Item/Item.test.d.ts +0 -2
  131. package/dist/types/__tests__/node/Item/Item.test.d.ts.map +0 -1
  132. package/dist/types/__tests__/node/setup.d.ts +0 -2
  133. package/dist/types/__tests__/node/setup.d.ts.map +0 -1
  134. package/dist/types/__tests__/scripts/bin.test.d.ts +0 -2
  135. package/dist/types/__tests__/scripts/bin.test.d.ts.map +0 -1
  136. package/dist/types/__tests__/setup.d.ts +0 -2
  137. package/dist/types/__tests__/setup.d.ts.map +0 -1
  138. package/dist/types/src/workers/content-hash.d.ts.map +0 -1
  139. /package/dist/types/src/{workers → browser/workers}/content-hash.d.ts +0 -0
@@ -1,7 +1,9 @@
1
1
  import { metadata, MetadataType } from '@/seedSchema'
2
- import { generateId } from '@/helpers'
2
+ import { BaseEasClient, BaseQueryClient, generateId } from '@/helpers'
3
3
  import { PropertyType } from '@/types'
4
4
  import { BaseDb } from '../Db/BaseDb'
5
+ import { GET_SCHEMA_BY_NAME, GET_SCHEMAS } from '@/Item/queries'
6
+ import { INTERNAL_DATA_TYPES } from '@/helpers/constants'
5
7
 
6
8
  type CreateMetadata = (
7
9
  metadataValues: Partial<MetadataType>,
@@ -20,15 +22,38 @@ export const createMetadata: CreateMetadata = async (
20
22
  metadataValues.modelType = metadataValues.modelName.toLowerCase()
21
23
  }
22
24
 
25
+ const isItemStorage = propertyRecordSchema && propertyRecordSchema.storageType === 'ItemStorage'
26
+
23
27
  if (
24
28
  propertyRecordSchema &&
25
29
  propertyRecordSchema.localStorageDir &&
26
- propertyRecordSchema.storageType === 'ItemStorage'
30
+ isItemStorage
27
31
  ) {
28
32
  metadataValues.refResolvedValue = `${metadataValues.seedUid || metadataValues.seedLocalId}${propertyRecordSchema.filenameSuffix}`
29
33
  metadataValues.refValueType = 'file'
30
34
  }
31
35
 
36
+ if (!isItemStorage && !metadataValues.schemaUid && propertyRecordSchema) {
37
+ const queryClient = BaseQueryClient.getQueryClient()
38
+ const easClient = BaseEasClient.getEasClient()
39
+
40
+ const easDataType = INTERNAL_DATA_TYPES[propertyRecordSchema.dataType].eas
41
+
42
+ const queryResult = await queryClient.fetchQuery({
43
+ queryKey: [`getSchemaByName${metadataValues.propertyName}`],
44
+ queryFn: async () =>
45
+ easClient.request(GET_SCHEMA_BY_NAME, {
46
+ where: {
47
+ schema: {
48
+ equals: `${easDataType} ${metadataValues.propertyName}`,
49
+ },
50
+ },
51
+ }),
52
+ })
53
+
54
+ metadataValues.schemaUid = queryResult.data[0].schema
55
+ }
56
+
32
57
  return appDb
33
58
  .insert(metadata)
34
59
  .values({
@@ -6,10 +6,7 @@ import { appState } from '@/seedSchema'
6
6
  import { eq } from 'drizzle-orm'
7
7
  import { getAddressesFromDb } from '@/helpers/db'
8
8
  import {
9
- getDataTypeFromString,
10
- getMimeType,
11
- identifyString,
12
- isBinary,
9
+ BaseFileManager,
13
10
  } from '@/helpers'
14
11
  import { GET_FILES_METADATA } from '@/schema/file/queries'
15
12
  import debug from 'debug'
@@ -102,37 +99,46 @@ export const downloadAllFilesBinaryRequestHandler = async () => {
102
99
  return []
103
100
  }
104
101
 
105
- for (const fileMetadata of filesMetadata) {
106
- const json = JSON.parse(fileMetadata.decodedDataJson)
107
- const transactionId = json[0].value.value
108
-
109
- const excludedTransactionsQuery = await appDb
102
+ const excludedTransactionsQuery = await appDb
110
103
  .select()
111
104
  .from(appState)
112
105
  .where(eq(appState.key, 'excludedTransactions'))
113
106
 
114
- let excludedTransactions = new Set<string>()
107
+ let excludedTransactions = new Set<string>()
115
108
 
116
- if (excludedTransactionsQuery && excludedTransactionsQuery.length === 1) {
117
- const valueString = excludedTransactionsQuery[0].value
118
- if (valueString) {
119
- const excludedTransactionsArray = JSON.parse(valueString)
120
- excludedTransactions = new Set(excludedTransactionsArray)
121
- }
109
+ if (excludedTransactionsQuery && excludedTransactionsQuery.length === 1) {
110
+ const valueString = excludedTransactionsQuery[0].value
111
+ if (valueString) {
112
+ const excludedTransactionsArray = JSON.parse(valueString)
113
+ excludedTransactions = new Set(excludedTransactionsArray)
122
114
  }
115
+ }
123
116
 
117
+ const transactionIds = []
118
+
119
+ for (const fileMetadata of filesMetadata) {
120
+ const json = JSON.parse(fileMetadata.decodedDataJson)
121
+ const transactionId = json[0].value.value
124
122
  if (excludedTransactions.has(transactionId)) {
125
123
  continue
126
124
  }
125
+ transactionIds.push(transactionId)
126
+ }
127
127
 
128
- const arweave = getArweave()
128
+ const arweave = getArweave()
129
129
 
130
- if (!arweave) {
131
- console.warn(
132
- '[fetchAll/actors] [fetchAllBinaryData] arweave not available',
133
- )
134
- return []
135
- }
130
+ if (!arweave) {
131
+ console.warn(
132
+ '[fetchAll/actors] [fetchAllBinaryData] arweave not available',
133
+ )
134
+ return []
135
+ }
136
+
137
+ const arweaveClient = BaseArweaveClient.getArweaveClient()
138
+
139
+ const transactionIdsToDownload = []
140
+
141
+ for (const transactionId of transactionIds) {
136
142
 
137
143
  try {
138
144
  const res = await fetch(
@@ -153,9 +159,7 @@ export const downloadAllFilesBinaryRequestHandler = async () => {
153
159
 
154
160
  continue
155
161
  }
156
-
157
- const arweaveClient = BaseArweaveClient.getArweaveClient()
158
-
162
+
159
163
  const { tags: tagsResult } = await queryClient.fetchQuery({
160
164
  queryKey: ['getTransactionTags', transactionId],
161
165
  queryFn: async () =>
@@ -182,186 +186,25 @@ export const downloadAllFilesBinaryRequestHandler = async () => {
182
186
  }
183
187
  }
184
188
 
185
- const data = await queryClient.fetchQuery({
186
- queryKey: ['fetchTransaction', transactionId],
187
- queryFn: async () => {
188
- const response = await fetch(
189
- `https://${ARWEAVE_HOST}/raw/${transactionId}`,
190
- )
191
-
192
- const arrayBuffer = await response.arrayBuffer()
193
- if (isBinary(arrayBuffer)) {
194
- return arrayBuffer
195
- }
196
-
197
- const decoder = new TextDecoder('utf-8')
198
- const text = decoder.decode(arrayBuffer)
199
-
200
- return text
201
- },
202
- networkMode: 'offlineFirst',
203
- })
204
-
205
- let dataString
206
- let arrayBuffer
207
-
208
- if (data instanceof ArrayBuffer) {
209
- arrayBuffer = data
210
- }
211
-
212
- if (typeof data === 'string') {
213
- dataString = data
214
- }
215
-
216
- // const dataString = await arweave.transactions.getData(transactionId, {
217
- // decode: true,
218
- // string: true,
219
- // })
220
-
221
- if (!dataString && !arrayBuffer) {
222
- logger(
223
- `[fetchAll/actors] [fetchAllBinaryData] transaction ${transactionId} data not found`,
224
- )
225
- }
226
-
227
- if (dataString && dataString.startsWith('===FILE_SEPARATOR===')) {
228
- const dataStringParts = dataString
229
- .split('===FILE_SEPARATOR===')
230
- .slice(1)
231
-
232
- if (dataStringParts.length % 2 !== 0) {
233
- throw new Error('Input array must have an even number of elements.')
234
- }
235
-
236
- for (let i = 0; i < dataStringParts.length; i += 2) {
237
- const contentType = dataStringParts[i]
238
- const content = dataStringParts[i + 1]
239
- if (contentType === 'html') {
240
- const fileName = `${transactionId}.html`
241
- fs.writeFileSync(`/files/html/${fileName}`, content)
242
- }
243
- if (contentType === 'json') {
244
- const fileName = `${transactionId}.json`
245
- fs.writeFileSync(`/files/json/${fileName}`, content)
246
- }
247
- }
248
-
249
- continue
250
- }
251
-
252
- if (!dataString && arrayBuffer) {
253
- await fs.writeFileSync(
254
- `/files/images/${transactionId}`,
255
- new Uint8Array(arrayBuffer),
256
- )
257
- continue
258
- }
259
-
260
- if (!dataString) {
261
- continue
262
- }
263
-
264
- let contentType = identifyString(dataString)
265
- if (
266
- contentType !== 'json' &&
267
- contentType !== 'base64' &&
268
- contentType !== 'html'
269
- ) {
270
- const possibleImageType = getDataTypeFromString(dataString)
271
- if (!possibleImageType) {
272
- logger(
273
- `[fetchAll/actors] [fetchAllBinaryData] transaction ${transactionId} data not in expected format: ${possibleImageType}`,
274
- )
275
- continue
276
- }
277
-
278
- contentType = possibleImageType
279
- }
280
-
281
- if (contentType === 'url') {
282
- const url = dataString as string
283
- const response = await fetch(url)
284
- if (!response.ok) {
285
- throw new Error(`Failed to fetch image: ${response.statusText}`)
286
- }
287
-
288
- // Get the image as a Blob
289
- const blob = await response.blob()
290
- const buffer = await blob.arrayBuffer()
291
- const bufferUint8Array = new Uint8Array(buffer)
292
-
293
- // Extract the file extension from the URL
294
- const extensionMatch = url.match(/\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i)
295
- if (!extensionMatch) {
296
- throw new Error(
297
- 'Unable to determine the file extension from the URL.',
298
- )
299
- }
300
- const fileExtension = extensionMatch[0] // e.g., ".jpg"
301
-
302
- // Set the file name (you can customize this)
303
- // const fileNameFromUrl = `${transactionId}${fileExtension}`
304
-
305
- await fs.promises.writeFile(
306
- `/files/images/${transactionId}`,
307
- bufferUint8Array,
308
- {
309
- encoding: 'binary',
310
- },
311
- )
312
-
313
- continue
314
- }
315
-
316
- const mimeType = getMimeType(dataString as string)
317
- let fileExtension = mimeType
318
-
319
- if (fileExtension && fileExtension?.startsWith('image')) {
320
- fileExtension = fileExtension.replace('image/', '')
321
- }
322
-
323
- let fileName = transactionId
324
-
325
- if (contentType === 'base64') {
326
- if (fileExtension) {
327
- fileName += `.${fileExtension}`
328
- }
329
-
330
- // Remove the Base64 header if it exists (e.g., "data:image/png;base64,")
331
- const base64Data = dataString.split(',').pop() || ''
332
-
333
- // Decode the Base64 string to binary
334
- const binaryString = atob(base64Data)
335
- const length = binaryString.length
336
- const binaryData = new Uint8Array(length)
337
-
338
- for (let i = 0; i < length; i++) {
339
- binaryData[i] = binaryString.charCodeAt(i)
340
- }
341
-
342
- await fs.promises.writeFile(`/files/images/${fileName}`, binaryData, {
343
- encoding: 'binary',
344
- })
345
-
346
- // if (dataUint8Array && dataUint8Array instanceof Uint8Array) {
347
- // await fs.promises.writeFile(
348
- // `/files/images/${fileName}`,
349
- // dataUint8Array,
350
- // )
351
- // }
352
- }
189
+ transactionIdsToDownload.push(transactionId)
353
190
 
354
- if (contentType === 'html') {
355
- fileName += '.html'
356
- await fs.promises.writeFile(`/files/html/${fileName}`, dataString)
357
- }
191
+
358
192
 
359
- if (contentType === 'json') {
360
- fileName += '.json'
361
- await fs.promises.writeFile(`/files/json/${fileName}`, dataString)
362
- }
363
193
  } catch (error) {
364
194
  logger(error)
365
195
  }
366
196
  }
197
+
198
+ console.log('[download] Calling downloadAllFiles with transactionIdsToDownload', transactionIdsToDownload)
199
+
200
+ await BaseFileManager.downloadAllFiles({
201
+ transactionIds: transactionIdsToDownload,
202
+ arweaveHost: ARWEAVE_HOST,
203
+ excludedTransactions,
204
+ })
205
+
206
+ await BaseFileManager.resizeAllImages({
207
+ width: 480,
208
+ height: 480,
209
+ })
367
210
  }
@@ -0,0 +1,326 @@
1
+
2
+ export default `(
3
+ ${
4
+ function () {
5
+
6
+ const identifyString = (str: string) => {
7
+ try {
8
+ JSON.parse(str)
9
+ return 'json'
10
+ } catch (e) {
11
+ // Not JSON
12
+ }
13
+
14
+ if (!str) {
15
+ return
16
+ }
17
+
18
+ if (str.trim().startsWith('<') && str.trim().endsWith('>')) {
19
+ return 'html'
20
+ }
21
+
22
+ // Simple markdown checks (very naive)
23
+ if (/^#{1,6}\s|^-{3,}|\*{3,}|^-{1,2}\s|\*\s/.test(str)) {
24
+ return 'markdown'
25
+ }
26
+
27
+ if (/^data:image\/[a-zA-Z]+;base64,[A-Za-z0-9+/]+={0,2}$/.test(str)) {
28
+ return 'base64'
29
+ }
30
+
31
+ // Default to plain text if unsure
32
+ return 'text'
33
+ }
34
+
35
+ const getMimeType = (base64: string) => {
36
+ if (!base64) {
37
+ return null
38
+ }
39
+ const result = base64.match(/^data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,/)
40
+
41
+ if (result && result.length > 1) {
42
+ return result[1]
43
+ } else {
44
+ return null // MIME type could not be determined
45
+ }
46
+ }
47
+
48
+ const getDataTypeFromString = (
49
+ data: string,
50
+ ): 'imageBase64' | 'base64' | 'url' | null => {
51
+ const nonImageBase64Regex =
52
+ /^(?!data:image\/(?:jpeg|png|gif|bmp|webp);base64,)[A-Za-z0-9+/=]+$/
53
+
54
+ if (nonImageBase64Regex.test(data)) {
55
+ return 'base64'
56
+ }
57
+
58
+ // Regular expression for base64 (simple version, checking for base64 format)
59
+ const imageBase64Regex = /^data:image\/[a-zA-Z]+;base64,[A-Za-z0-9+/]+={0,2}$/
60
+
61
+ if (imageBase64Regex.test(data)) {
62
+ return 'imageBase64'
63
+ }
64
+
65
+ // Regular expression for URL (simple version, checking for common URL format)
66
+ const urlRegex =
67
+ /^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/
68
+
69
+ if (urlRegex.test(data)) {
70
+ return 'url'
71
+ }
72
+
73
+ return null
74
+ }
75
+
76
+ const isBinary = (arrayBuffer: ArrayBuffer): boolean => {
77
+ const view = new Uint8Array(arrayBuffer);
78
+
79
+ let nonTextCount = 0;
80
+ const threshold = 0.2; // Adjust as needed (e.g., 20% non-text implies binary)
81
+
82
+ for (let i = 0; i < view.length; i++) {
83
+ const byte = view[i];
84
+
85
+ // ASCII printable characters (32-126) and common whitespace (9, 10, 13)
86
+ if (
87
+ (byte >= 32 && byte <= 126) || // Printable ASCII
88
+ byte === 9 || byte === 10 || byte === 13 // Tab, LF, CR
89
+ ) {
90
+ continue;
91
+ }
92
+
93
+ nonTextCount++;
94
+ if (nonTextCount / view.length > threshold) {
95
+ return true; // More than threshold are non-text bytes
96
+ }
97
+ }
98
+
99
+ return false; // Fewer than threshold are non-text bytes
100
+ }
101
+
102
+ const saveBufferToOPFS = async (filePath: string, buffer: Uint8Array): Promise<void> => {
103
+ // Access the OPFS root directory
104
+ const rootHandle = await navigator.storage.getDirectory();
105
+
106
+ // Split the filePath into directory segments and file name
107
+ const segments = filePath.split('/').filter(Boolean);
108
+ const fileName = segments.pop(); // Extract the file name
109
+ if (!fileName) {
110
+ throw new Error('Invalid file path: No file name provided.');
111
+ }
112
+
113
+ // Traverse or create directories as needed
114
+ let currentDirHandle = rootHandle;
115
+ for (const segment of segments) {
116
+ currentDirHandle = await currentDirHandle.getDirectoryHandle(segment, { create: true });
117
+ }
118
+
119
+ // Create or open the file in OPFS
120
+ const fileHandleAsync = await currentDirHandle.getFileHandle(fileName, { create: true });
121
+ const fileHandle = await fileHandleAsync.createSyncAccessHandle();
122
+ // Write the buffer to the file
123
+ fileHandle.write(buffer);
124
+ fileHandle.flush();
125
+ fileHandle.close();
126
+ }
127
+
128
+ const downloadFiles = async ({
129
+ transactionIds,
130
+ arweaveHost,
131
+ }: {
132
+ transactionIds: string[],
133
+ arweaveHost: string,
134
+ }) => {
135
+
136
+ let arrayBuffer: ArrayBuffer | undefined
137
+
138
+ for (const transactionId of transactionIds) {
139
+ try {
140
+ const response = await fetch(`https://${arweaveHost}/raw/${transactionId}`);
141
+
142
+ arrayBuffer = await response.arrayBuffer();
143
+ } catch(error) {
144
+ console.log(`[filesDownload] transaction ${transactionId} data not found`, error)
145
+ globalThis.postMessage({
146
+ message: 'excludeTransaction',
147
+ transactionId,
148
+ })
149
+ continue
150
+ }
151
+
152
+ let dataString
153
+ const isBinaryData = isBinary(arrayBuffer)
154
+
155
+ if (!isBinaryData) {
156
+ const decoder = new TextDecoder('utf-8')
157
+ const text = decoder.decode(arrayBuffer)
158
+ dataString = text
159
+ }
160
+
161
+ if (!dataString && !arrayBuffer) {
162
+ console.log(
163
+ `[filesDownload] transaction ${transactionId} data not found`,
164
+ )
165
+ }
166
+
167
+ if (dataString && dataString.startsWith('===FILE_SEPARATOR===')) {
168
+ const dataStringParts = dataString
169
+ .split('===FILE_SEPARATOR===')
170
+ .slice(1)
171
+
172
+ if (dataStringParts.length % 2 !== 0) {
173
+ throw new Error('Input array must have an even number of elements.')
174
+ }
175
+
176
+ for (let i = 0; i < dataStringParts.length; i += 2) {
177
+ const contentType = dataStringParts[i]
178
+ const content = dataStringParts[i + 1]
179
+ const encoder = new TextEncoder()
180
+ if (contentType === 'html') {
181
+ const fileName = `${transactionId}.html`
182
+ const buffer = encoder.encode(content)
183
+ saveBufferToOPFS(`/files/html/${fileName}`, buffer)
184
+ }
185
+ if (contentType === 'json') {
186
+ const fileName = `${transactionId}.json`
187
+ const buffer = encoder.encode(content)
188
+ saveBufferToOPFS(`/files/json/${fileName}`, buffer)
189
+ }
190
+ }
191
+
192
+ continue
193
+ }
194
+
195
+ if (!dataString && arrayBuffer) {
196
+ saveBufferToOPFS(
197
+ `/files/images/${transactionId}`,
198
+ new Uint8Array(arrayBuffer),
199
+ )
200
+ continue
201
+ }
202
+
203
+ if (!dataString) {
204
+ continue
205
+ }
206
+
207
+ let contentType = identifyString(dataString)
208
+
209
+ if (
210
+ contentType !== 'json' &&
211
+ contentType !== 'base64' &&
212
+ contentType !== 'html'
213
+ ) {
214
+ const possibleImageType = getDataTypeFromString(dataString)
215
+ if (!possibleImageType) {
216
+ console.log(
217
+ `[filesDownload] transaction ${transactionId} data not in expected format: ${possibleImageType}`,
218
+ )
219
+ continue
220
+ }
221
+
222
+ contentType = possibleImageType
223
+ }
224
+
225
+ if (contentType === 'url') {
226
+ const url = dataString as string
227
+
228
+ let buffer: ArrayBuffer | undefined
229
+
230
+ try {
231
+ const response = await fetch(url)
232
+
233
+ buffer = await response.arrayBuffer()
234
+
235
+ } catch(error) {
236
+ console.log(`[filesDownload] transaction ${transactionId} value was url: ${dataString} but failed to fetch`, error)
237
+ globalThis.postMessage({
238
+ message: 'excludeTransaction',
239
+ transactionId,
240
+ })
241
+ continue
242
+ }
243
+
244
+ const bufferUint8Array = new Uint8Array(buffer)
245
+
246
+ // Extract the file extension from the URL
247
+ const extensionMatch = url.match(/\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i)
248
+ if (!extensionMatch) {
249
+ throw new Error(
250
+ 'Unable to determine the file extension from the URL.',
251
+ )
252
+ }
253
+ const fileExtension = extensionMatch[0] // e.g., ".jpg"
254
+
255
+ // Set the file name (you can customize this)
256
+ // const fileNameFromUrl = `${transactionId}${fileExtension}`
257
+
258
+ await saveBufferToOPFS(
259
+ `/files/images/${transactionId}`,
260
+ bufferUint8Array,
261
+ )
262
+
263
+ continue
264
+ }
265
+
266
+ const mimeType = getMimeType(dataString as string)
267
+ let fileExtension = mimeType
268
+
269
+ if (fileExtension && fileExtension?.startsWith('image')) {
270
+ fileExtension = fileExtension.replace('image/', '')
271
+ }
272
+
273
+ let fileName = transactionId
274
+
275
+ if (contentType === 'base64') {
276
+ if (fileExtension) {
277
+ fileName += `.${fileExtension}`
278
+ }
279
+
280
+ // Remove the Base64 header if it exists (e.g., "data:image/png;base64,")
281
+ const base64Data = dataString.split(',').pop() || ''
282
+
283
+ // Decode the Base64 string to binary
284
+ const binaryString = atob(base64Data)
285
+ const length = binaryString.length
286
+ const binaryData = new Uint8Array(length)
287
+
288
+ for (let i = 0; i < length; i++) {
289
+ binaryData[i] = binaryString.charCodeAt(i)
290
+ }
291
+
292
+ await saveBufferToOPFS(`/files/images/${fileName}`, binaryData)
293
+
294
+ }
295
+
296
+ if (contentType === 'html') {
297
+ fileName += '.html'
298
+ const encoder = new TextEncoder()
299
+ const buffer = encoder.encode(dataString)
300
+ await saveBufferToOPFS(`/files/html/${fileName}`, buffer)
301
+ }
302
+
303
+ if (contentType === 'json') {
304
+ fileName += '.json'
305
+ const encoder = new TextEncoder()
306
+ const buffer = encoder.encode(dataString)
307
+ await saveBufferToOPFS(`/files/json/${fileName}`, buffer)
308
+ }
309
+ }
310
+ }
311
+
312
+ onmessage = async (e) => {
313
+ console.log({
314
+ message: 'filesDownload onmessage',
315
+ data: e.data,
316
+ })
317
+ await downloadFiles(e.data);
318
+ globalThis.postMessage({
319
+ message: 'filesDownload onmessage done',
320
+ done: true,
321
+ })
322
+
323
+ }
324
+ }.toString()
325
+ }
326
+ )()`
@@ -1,6 +1,7 @@
1
1
  import { getItemData } from './getItemData'
2
2
  import { GetItem } from '@/types'
3
3
  import { BaseItem } from '@/Item/BaseItem'
4
+ import { startCase } from 'lodash-es'
4
5
 
5
6
  export const getItem: GetItem = async ({ modelName, seedLocalId, seedUid }) => {
6
7
  const itemInitObj = await getItemData({
@@ -23,5 +24,9 @@ export const getItem: GetItem = async ({ modelName, seedLocalId, seedUid }) => {
23
24
  return
24
25
  }
25
26
 
27
+ if (!itemInitObj.modelName && itemInitObj.type) {
28
+ itemInitObj.modelName = startCase(itemInitObj.type)
29
+ }
30
+
26
31
  return BaseItem.create(itemInitObj)
27
32
  }