@seedprotocol/sdk 0.2.54 → 0.3.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.
Files changed (243) hide show
  1. package/dist/{ArweaveClient-D5iJisYr.js → ArweaveClient-C0g0es2v.js} +2 -2
  2. package/dist/{ArweaveClient-D5iJisYr.js.map → ArweaveClient-C0g0es2v.js.map} +1 -1
  3. package/dist/{ArweaveClient-HEIIuOfB.js → ArweaveClient-CzkBgiZY.js} +2 -2
  4. package/dist/{ArweaveClient-HEIIuOfB.js.map → ArweaveClient-CzkBgiZY.js.map} +1 -1
  5. package/dist/{Db-jMth8Y2g.js → Db-C4oog-0n.js} +4 -3
  6. package/dist/{Db-jMth8Y2g.js.map → Db-C4oog-0n.js.map} +1 -1
  7. package/dist/Db-VPouegkr.js +82 -0
  8. package/dist/Db-VPouegkr.js.map +1 -0
  9. package/dist/EasClient-B9a3NsTi.js +10 -0
  10. package/dist/EasClient-B9a3NsTi.js.map +1 -0
  11. package/dist/{EasClient-D3wKgt0o.js → EasClient-DQ93i2ci.js} +2 -2
  12. package/dist/{EasClient-D3wKgt0o.js.map → EasClient-DQ93i2ci.js.map} +1 -1
  13. package/dist/{FileManager-4mWYO3Mt.js → FileManager-_ErxVuwb.js} +9 -5
  14. package/dist/FileManager-_ErxVuwb.js.map +1 -0
  15. package/dist/{Item-CbgjLSUx.js → Item-D9HFPxsK.js} +4 -3
  16. package/dist/{Item-CbgjLSUx.js.map → Item-D9HFPxsK.js.map} +1 -1
  17. package/dist/{ItemProperty-DduurIcl.js → ItemProperty-BdtvKrEy.js} +4 -3
  18. package/dist/{ItemProperty-DduurIcl.js.map → ItemProperty-BdtvKrEy.js.map} +1 -1
  19. package/dist/QueryClient-Bmnv_moN.js +22 -0
  20. package/dist/QueryClient-Bmnv_moN.js.map +1 -0
  21. package/dist/{QueryClient-CBOP3OoU.js → QueryClient-hzOtFe99.js} +3 -2
  22. package/dist/{QueryClient-CBOP3OoU.js.map → QueryClient-hzOtFe99.js.map} +1 -1
  23. package/dist/bin.js +30 -34
  24. package/dist/bin.js.map +1 -1
  25. package/dist/{constants-CIDbABDz.js → constants-Bhl5dZpN.js} +9 -4
  26. package/dist/constants-Bhl5dZpN.js.map +1 -0
  27. package/dist/db/configs/node.app.db.config.ts +27 -0
  28. package/dist/{index-DQNTvzqi.js → index-BAtjd9W-.js} +4 -3
  29. package/dist/index-BAtjd9W-.js.map +1 -0
  30. package/dist/{index-CTZqN6WI.js → index-BSR5hv7Q.js} +305 -268
  31. package/dist/index-BSR5hv7Q.js.map +1 -0
  32. package/dist/main.js +3 -2
  33. package/dist/main.js.map +1 -1
  34. package/dist/node/db/node.app.db.config.ts +1 -1
  35. package/dist/{seed.schema.config-B-4U2RRq.js → seed.schema.config-BxJYabim.js} +10 -9
  36. package/dist/seed.schema.config-BxJYabim.js.map +1 -0
  37. package/dist/src/AppStateSchema.ts +10 -0
  38. package/dist/src/ArweaveClient.ts +13 -0
  39. package/dist/src/Attestation.ts +21 -0
  40. package/dist/src/BaseArweaveClient.ts +13 -0
  41. package/dist/src/BaseClientManager.ts +35 -0
  42. package/dist/src/BaseDb.ts +35 -0
  43. package/dist/src/BaseEasClient.ts +14 -0
  44. package/dist/src/BaseFileManager.ts +60 -0
  45. package/dist/src/BaseItem.ts +413 -0
  46. package/dist/src/BaseItemProperty.ts +416 -0
  47. package/dist/src/BaseQueryClient.ts +13 -0
  48. package/dist/src/ClientManager.ts +63 -0
  49. package/dist/src/ConfigSchema.ts +15 -0
  50. package/dist/src/Db.ts +82 -0
  51. package/dist/src/EasClient.ts +13 -0
  52. package/dist/src/FileDownloader.ts +63 -0
  53. package/dist/src/FileManager.ts +59 -0
  54. package/dist/src/IDb.ts +7 -0
  55. package/dist/src/IEasClient.ts +2 -0
  56. package/dist/src/IItem.ts +26 -0
  57. package/dist/src/IItemProperty.ts +28 -0
  58. package/dist/src/IQueryClient.ts +11 -0
  59. package/dist/src/ImageResizer.ts +81 -0
  60. package/dist/src/Item.ts +12 -0
  61. package/dist/src/ItemProperty.ts +9 -0
  62. package/dist/src/MetadataSchema.ts +28 -0
  63. package/dist/src/ModelSchema.ts +46 -0
  64. package/dist/src/ModelUidSchema.ts +16 -0
  65. package/dist/src/PropertyUidSchema.ts +16 -0
  66. package/dist/src/QueryClient.ts +26 -0
  67. package/dist/src/Schema.ts +17 -0
  68. package/dist/src/SeedProtocolSdk.d.ts +19 -0
  69. package/dist/src/SeedSchema.ts +29 -0
  70. package/dist/src/VersionSchema.ts +16 -0
  71. package/dist/src/actors.ts +295 -0
  72. package/dist/src/addModelsToDb.ts +152 -0
  73. package/dist/src/allItems.ts +31 -0
  74. package/dist/src/analyzeInput.ts +144 -0
  75. package/dist/src/browser.app.db.config.ts +27 -0
  76. package/dist/src/browser.ts +30 -0
  77. package/dist/src/checkStatus.ts +57 -0
  78. package/dist/src/clientManagerMachine.ts +59 -0
  79. package/dist/src/configureFs.ts +98 -0
  80. package/dist/src/connectToDb.ts +41 -0
  81. package/dist/src/connectionManager.ts +67 -0
  82. package/dist/src/constants.ts +125 -0
  83. package/dist/src/content-hash.ts +30 -0
  84. package/dist/src/create.ts +39 -0
  85. package/dist/src/createMetadata.ts +77 -0
  86. package/dist/src/createNewItem.ts +61 -0
  87. package/dist/src/createPublishAttempt.ts +16 -0
  88. package/dist/src/createSeed.ts +31 -0
  89. package/dist/src/createSeeds.ts +24 -0
  90. package/dist/src/createVersion.ts +33 -0
  91. package/dist/src/dbMachine.ts +182 -0
  92. package/dist/src/deleteItem.ts +19 -0
  93. package/dist/src/download.ts +208 -0
  94. package/dist/src/drizzle.ts +78 -0
  95. package/dist/src/eas.ts +40 -0
  96. package/dist/src/environment.ts +35 -0
  97. package/dist/src/eventBus.ts +5 -0
  98. package/dist/src/events.ts +14 -0
  99. package/dist/src/fetchDataFromEas.ts +94 -0
  100. package/dist/src/fetchDbData.ts +19 -0
  101. package/dist/src/fetchRelatedItems.ts +184 -0
  102. package/dist/src/fetchSeeds.ts +45 -0
  103. package/dist/src/fetchVersions.ts +49 -0
  104. package/dist/src/files.ts +81 -0
  105. package/dist/src/filesDownload.ts +326 -0
  106. package/dist/src/fragment-masking.ts +87 -0
  107. package/dist/src/getExistingItem.ts +60 -0
  108. package/dist/src/getItem.ts +32 -0
  109. package/dist/src/getItemData.ts +99 -0
  110. package/dist/src/getItemProperties.ts +56 -0
  111. package/dist/src/getItemProperty.ts +34 -0
  112. package/dist/src/getItems.ts +70 -0
  113. package/dist/src/getMetadata.ts +40 -0
  114. package/dist/src/getModelSchemas.ts +89 -0
  115. package/dist/src/getPropertyData.ts +50 -0
  116. package/dist/src/getPublishPayload.ts +355 -0
  117. package/dist/src/getPublishUploads.ts +207 -0
  118. package/dist/src/getRelationValueData.ts +27 -0
  119. package/dist/src/getSchemaForItemProperty.ts +68 -0
  120. package/dist/src/getSchemaForModel.ts +42 -0
  121. package/dist/src/getSchemaUidForModel.ts +32 -0
  122. package/dist/src/getSeedData.ts +34 -0
  123. package/dist/src/getSegmentedItemProperties.ts +65 -0
  124. package/dist/src/getStorageTransactionIdForSeedUid.ts +38 -0
  125. package/dist/src/getVersionData.ts +46 -0
  126. package/dist/src/getVersionsForVersionUids.ts +39 -0
  127. package/dist/src/globalMachine.ts +280 -0
  128. package/dist/src/gql.ts +118 -0
  129. package/dist/src/graphql.ts +3209 -0
  130. package/dist/src/helpers.ts +273 -0
  131. package/dist/src/hydrateExistingItem.ts +137 -0
  132. package/dist/src/hydrateFromDb.ts +270 -0
  133. package/dist/src/hydrateNewItem.ts +34 -0
  134. package/dist/src/imageResize.ts +507 -0
  135. package/dist/src/index.d.ts +5 -0
  136. package/dist/src/index.ts +4 -0
  137. package/dist/src/initialize.ts +124 -0
  138. package/dist/src/internalMachine.ts +241 -0
  139. package/dist/src/itemMachineAll.ts +157 -0
  140. package/dist/src/itemMachineSingle.ts +158 -0
  141. package/dist/src/loadAppDb.ts +44 -0
  142. package/dist/src/machines.ts +66 -0
  143. package/dist/src/metadataLatest.ts +34 -0
  144. package/dist/src/migrate.ts +57 -0
  145. package/dist/src/model.ts +72 -0
  146. package/dist/src/modelClass.ts +19 -0
  147. package/dist/src/node.app.db.config.ts +41 -0
  148. package/dist/src/prepareDb.ts +29 -0
  149. package/dist/src/preparePublishRequestData.ts +81 -0
  150. package/dist/src/processItems.ts +74 -0
  151. package/dist/src/property.ts +156 -0
  152. package/dist/src/propertyMachine.ts +202 -0
  153. package/dist/src/publish.ts +28 -0
  154. package/dist/src/publishMachine.ts +77 -0
  155. package/dist/src/queries.ts +13 -0
  156. package/dist/src/recoverDeletedItem.ts +14 -0
  157. package/dist/src/reload.ts +33 -0
  158. package/dist/src/request.ts +45 -0
  159. package/dist/src/requestAll.ts +157 -0
  160. package/dist/src/resolveRelatedValue.ts +367 -0
  161. package/dist/src/resolveRemoteStorage.ts +88 -0
  162. package/dist/src/saveAppState.ts +50 -0
  163. package/dist/src/saveConfig.ts +106 -0
  164. package/dist/src/saveDataToDb.ts +145 -0
  165. package/dist/src/saveImageSrc.ts +242 -0
  166. package/dist/src/saveItemStorage.ts +156 -0
  167. package/dist/src/saveMetadata.ts +18 -0
  168. package/dist/src/savePublishService.ts +30 -0
  169. package/dist/src/saveRelation.ts +112 -0
  170. package/dist/src/seed.schema.config.ts +25 -0
  171. package/dist/src/seed.ts +10 -0
  172. package/dist/src/seedProtocol.ts +17 -0
  173. package/dist/src/services.ts +365 -0
  174. package/dist/src/setAddresses.ts +16 -0
  175. package/dist/src/sqlWasmClient.ts +88 -0
  176. package/dist/src/syncDbWithEas.ts +628 -0
  177. package/dist/src/trash.ts +29 -0
  178. package/dist/src/ts-to-proto.ts +101 -0
  179. package/dist/src/types.ts +12 -0
  180. package/dist/src/updateItemPropertyValue.ts +243 -0
  181. package/dist/src/updateMachineContext.ts +21 -0
  182. package/dist/src/updateMetadata.ts +59 -0
  183. package/dist/src/upload.ts +86 -0
  184. package/dist/src/validate.ts +45 -0
  185. package/dist/src/validateInput.ts +43 -0
  186. package/dist/src/validateItemData.ts +20 -0
  187. package/dist/src/versionData.ts +24 -0
  188. package/dist/src/waitForDb.ts +25 -0
  189. package/dist/src/waitForFiles.ts +41 -0
  190. package/dist/src/wasm.d.ts +8300 -0
  191. package/dist/types/scripts/bin.d.ts.map +1 -1
  192. package/dist/types/src/browser/helpers/EasClient.d.ts +1 -3
  193. package/dist/types/src/browser/helpers/EasClient.d.ts.map +1 -1
  194. package/dist/types/src/browser/helpers/FileManager.d.ts +2 -1
  195. package/dist/types/src/browser/helpers/FileManager.d.ts.map +1 -1
  196. package/dist/types/src/client/ClientManager.d.ts +44 -0
  197. package/dist/types/src/client/ClientManager.d.ts.map +1 -0
  198. package/dist/types/src/client/actions/setAddresses.d.ts.map +1 -1
  199. package/dist/types/src/client/actors/initialize.d.ts.map +1 -1
  200. package/dist/types/src/client/actors/saveAppState.d.ts.map +1 -1
  201. package/dist/types/src/client/clientManagerMachine.d.ts.map +1 -1
  202. package/dist/types/src/client/index.d.ts +2 -40
  203. package/dist/types/src/client/index.d.ts.map +1 -1
  204. package/dist/types/src/db/configs/node.app.db.config.d.ts +3 -0
  205. package/dist/types/src/db/configs/node.app.db.config.d.ts.map +1 -0
  206. package/dist/types/src/events/files/download.d.ts.map +1 -1
  207. package/dist/types/src/helpers/EasClient/BaseEasClient.d.ts.map +1 -1
  208. package/dist/types/src/helpers/FileManager/BaseFileManager.d.ts +1 -0
  209. package/dist/types/src/helpers/FileManager/BaseFileManager.d.ts.map +1 -1
  210. package/dist/types/src/helpers/constants.d.ts +1 -0
  211. package/dist/types/src/helpers/constants.d.ts.map +1 -1
  212. package/dist/types/src/interfaces/IQueryClient.d.ts +7 -1
  213. package/dist/types/src/interfaces/IQueryClient.d.ts.map +1 -1
  214. package/dist/types/src/node/db/Db.d.ts +5 -10
  215. package/dist/types/src/node/db/Db.d.ts.map +1 -1
  216. package/dist/types/src/node/helpers/FileManager.d.ts +2 -1
  217. package/dist/types/src/node/helpers/FileManager.d.ts.map +1 -1
  218. package/dist/types/src/node/helpers/QueryClient.d.ts +2 -4
  219. package/dist/types/src/node/helpers/QueryClient.d.ts.map +1 -1
  220. package/dist/types/src/services/allItems/actors/fetchSeeds.d.ts.map +1 -1
  221. package/dist/types/src/services/db/actors/checkStatus.d.ts.map +1 -1
  222. package/dist/types/src/services/db/actors/migrate.d.ts.map +1 -1
  223. package/dist/types/src/services/db/actors/waitForFiles.d.ts.map +1 -1
  224. package/dist/types/src/services/internal/actors/configureFs.d.ts.map +1 -1
  225. package/dist/types/src/services/internal/actors/loadAppDb.d.ts.map +1 -1
  226. package/dist/types/src/services/internal/actors/saveConfig.d.ts.map +1 -1
  227. package/dist/types/src/services/internal/actors/waitForFiles.d.ts.map +1 -1
  228. package/dist/types/src/services/internal/internalMachine.d.ts.map +1 -1
  229. package/package.json +10 -10
  230. package/dist/Db-DK9wSNIH.js +0 -120
  231. package/dist/Db-DK9wSNIH.js.map +0 -1
  232. package/dist/EasClient-jqkT2ZBt.js +0 -13
  233. package/dist/EasClient-jqkT2ZBt.js.map +0 -1
  234. package/dist/FileManager-4mWYO3Mt.js.map +0 -1
  235. package/dist/QueryClient-bKb3SB0W.js +0 -23
  236. package/dist/QueryClient-bKb3SB0W.js.map +0 -1
  237. package/dist/constants-CIDbABDz.js.map +0 -1
  238. package/dist/index-CTZqN6WI.js.map +0 -1
  239. package/dist/index-DQNTvzqi.js.map +0 -1
  240. package/dist/package.json +0 -189
  241. package/dist/seed.schema.config-B-4U2RRq.js.map +0 -1
  242. package/dist/types/src/client.d.ts +0 -18
  243. package/dist/types/src/client.d.ts.map +0 -1
@@ -0,0 +1,273 @@
1
+ import fs from '@zenfs/core'
2
+ import path from 'path'
3
+ import { Endpoints } from '@/types'
4
+ import { BROWSER_FS_TOP_DIR } from '@/services/internal/constants'
5
+ import debug from 'debug'
6
+ import { BaseFileManager } from '@/helpers/FileManager/BaseFileManager'
7
+
8
+ const logger = debug('app:services:internal:helpers')
9
+
10
+ /**
11
+ * Recursively create directories if they don't exist.
12
+ * @param {string} dirPath - The directory path to create.
13
+ */
14
+ export const createDirectories = async (dirPath: string) => {
15
+ const dirPathExists = await BaseFileManager.pathExists(dirPath)
16
+ if (dirPathExists) {
17
+ return
18
+ }
19
+
20
+ const parentDir = path.dirname(dirPath)
21
+ let parentDirExists = await BaseFileManager.pathExists(parentDir)
22
+ if (!parentDirExists) {
23
+ await createDirectories(parentDir)
24
+ }
25
+
26
+ parentDirExists = await BaseFileManager.pathExists(parentDir)
27
+ if (parentDirExists) {
28
+ await BaseFileManager.createDirIfNotExists(dirPath)
29
+ }
30
+ }
31
+
32
+ // export const downloadFile = async (url: string, localFilePath: string) => {
33
+ // try {
34
+ // const response = await fetch(url)
35
+ // const fileData = await response.text().catch((error) => {
36
+ // console.error(`Failed to parse text from ${url}:`, error)
37
+ // })
38
+ // if (!fileData) {
39
+ // console.error(`No file data from ${url}`)
40
+ // return
41
+ // }
42
+ // const localDirPath = path.dirname(localFilePath)
43
+
44
+ // if (busy) {
45
+ // return
46
+ // }
47
+
48
+ // busy = true
49
+
50
+ // await createDirectories(localDirPath)
51
+
52
+ // const filename = path.basename(localFilePath)
53
+
54
+ // const regex = /(\d+)[\w_]+\.(sql|json)$/
55
+
56
+ // const match = filename.match(regex)
57
+
58
+ // let migrationNumber
59
+
60
+ // if (match && match.length > 1) {
61
+ // migrationNumber = match[1]
62
+ // }
63
+
64
+ // if (migrationNumber) {
65
+ // const filesInDir = await fs.promises.readdir(localDirPath)
66
+ // for (const file of filesInDir) {
67
+ // if (file === filename) {
68
+ // continue
69
+ // }
70
+ // const innerMatch = file.match(regex)
71
+ // let existingFileMigrationNumber
72
+ // if (innerMatch && innerMatch.length > 1) {
73
+ // existingFileMigrationNumber = innerMatch[1]
74
+ // }
75
+ // if (
76
+ // migrationNumber &&
77
+ // existingFileMigrationNumber &&
78
+ // existingFileMigrationNumber === migrationNumber
79
+ // ) {
80
+ // await fs.promises.unlink(path.join(localDirPath, file))
81
+ // }
82
+ // }
83
+ // }
84
+
85
+ // try {
86
+
87
+ // await fs.promises.writeFile(localFilePath, fileData)
88
+ // logger(`[downloadFile] Wrote file async to ${localFilePath}`)
89
+ // } catch (error) {
90
+ // fs.writeFileSync(localFilePath, fileData)
91
+ // logger(`[downloadFile] Wrote file sync to ${localFilePath}`)
92
+ // }
93
+ // } catch (error) {
94
+ // logger(`[Error] Failed to download file from ${url}:`, error)
95
+ // }
96
+
97
+ // busy = false
98
+ // }
99
+
100
+ type DownloadFunction = (fileUrl: string) => Promise<void>;
101
+
102
+ class FileDownloadManager {
103
+ private filesToDownload: Map<string, number>;
104
+ private maxRetries: number;
105
+ private isDownloading: boolean = false;
106
+
107
+ constructor(fileUrls: string[], maxRetries: number) {
108
+ this.filesToDownload = new Map(fileUrls.map(url => [url, 0]));
109
+ this.maxRetries = maxRetries;
110
+ }
111
+
112
+ async downloadFile(url: string, localFilePath: string): Promise<void> {
113
+ const response = await fetch(url)
114
+ const fileData = await response.text().catch((error) => {
115
+ console.error(`Failed to parse text from ${url}:`, error)
116
+ })
117
+ if (!fileData) {
118
+ console.error(`No file data from ${url}`)
119
+ return
120
+ }
121
+ const localDirPath = path.dirname(localFilePath)
122
+
123
+ await createDirectories(localDirPath)
124
+
125
+ const filename = path.basename(localFilePath)
126
+
127
+ const regex = /(\d+)[\w_]+\.(sql|json)$/
128
+
129
+ const match = filename.match(regex)
130
+
131
+ let migrationNumber
132
+
133
+ if (match && match.length > 1) {
134
+ migrationNumber = match[1]
135
+ }
136
+
137
+ if (migrationNumber) {
138
+ const filesInDir = await fs.promises.readdir(localDirPath)
139
+ for (const file of filesInDir) {
140
+ if (file === filename) {
141
+ continue
142
+ }
143
+ const innerMatch = file.match(regex)
144
+ let existingFileMigrationNumber
145
+ if (innerMatch && innerMatch.length > 1) {
146
+ existingFileMigrationNumber = innerMatch[1]
147
+ }
148
+ if (
149
+ migrationNumber &&
150
+ existingFileMigrationNumber &&
151
+ existingFileMigrationNumber === migrationNumber
152
+ ) {
153
+ await fs.promises.unlink(path.join(localDirPath, file))
154
+ }
155
+ }
156
+ }
157
+
158
+ try {
159
+
160
+ await fs.promises.writeFile(localFilePath, fileData)
161
+ logger(`[downloadFile] Wrote file async to ${localFilePath}`)
162
+ } catch (error) {
163
+ fs.writeFileSync(localFilePath, fileData)
164
+ logger(`[downloadFile] Wrote file sync to ${localFilePath}`)
165
+ }
166
+
167
+ }
168
+
169
+ async start(): Promise<void> {
170
+ if (this.isDownloading) {
171
+ console.warn("Download process is already running.");
172
+ return;
173
+ }
174
+
175
+ this.isDownloading = true;
176
+
177
+ for (const [fileUrl, attempts] of this.filesToDownload.entries()) {
178
+ let success = false;
179
+
180
+ while (attempts < this.maxRetries) {
181
+ try {
182
+ console.log(`Starting download: ${fileUrl}`);
183
+ await this.downloadFile(fileUrl, fileUrl);
184
+ console.log(`Download successful: ${fileUrl}`);
185
+ this.filesToDownload.delete(fileUrl);
186
+ success = true;
187
+ break; // Move to next file
188
+ } catch (error) {
189
+ console.error(`Error downloading ${fileUrl}:`, error);
190
+ this.filesToDownload.set(fileUrl, attempts + 1);
191
+ }
192
+ }
193
+
194
+ if (!success) {
195
+ console.error(`Failed to download after ${this.maxRetries} attempts: ${fileUrl}`);
196
+ }
197
+ }
198
+
199
+ this.isDownloading = false;
200
+ console.log("All downloads completed.");
201
+ }
202
+
203
+ addFile(fileUrl: string): void {
204
+ if (!this.filesToDownload.has(fileUrl)) {
205
+ this.filesToDownload.set(fileUrl, 0);
206
+ console.log(`Added file to download queue: ${fileUrl}`);
207
+ } else {
208
+ console.warn(`File already in queue: ${fileUrl}`);
209
+ }
210
+ }
211
+
212
+ getPendingFiles(): string[] {
213
+ return Array.from(this.filesToDownload.keys());
214
+ }
215
+
216
+ clear(): void {
217
+ this.filesToDownload.clear();
218
+ console.log("Cleared all files from the download queue.");
219
+ }
220
+ }
221
+
222
+
223
+ export const fetchDirectory = async (url: string) => {
224
+ const response = await fetch(url)
225
+ return response.json()
226
+ }
227
+
228
+ // export const fetchFilesRecursively = async (
229
+ // url: string,
230
+ // localPath: string,
231
+ // fileList: string[],
232
+ // ) => {
233
+ // for (const file of fileList) {
234
+ // try {
235
+ // const fileUrl = `${url}/${file}`
236
+ // const fileLocalPath = path.join(localPath, file)
237
+
238
+ // // logger(`[fetchFilesRecursively] fileUrl: ${fileUrl}`)
239
+ // // logger(`[fetchFilesRecursively] fileLocalPath: ${fileLocalPath}`)
240
+
241
+ // await downloadFile(fileUrl, fileLocalPath)
242
+ // } catch (error) {
243
+ // console.error(`Failed to fetch files from ${url}:`, error)
244
+ // }
245
+ // }
246
+ // }
247
+
248
+ export const confirmFilesExist = async (filePaths: string[]) => {
249
+ let everythingDownloaded = false
250
+
251
+ for (const filePath of filePaths) {
252
+ everythingDownloaded = await fs.promises.exists(filePath)
253
+ }
254
+
255
+ if (!everythingDownloaded) {
256
+ setTimeout(async () => {
257
+ await confirmFilesExist(filePaths)
258
+ }, 500)
259
+ }
260
+ }
261
+
262
+ const filesToExclude = ['.DS_Store']
263
+
264
+ export const syncDbFiles = async ({ filePaths, files }: Endpoints) => {
265
+ let fileList = await fetchDirectory(filePaths)
266
+ fileList = fileList.filter((file: string) => !filesToExclude.includes(file))
267
+ fileList = fileList.map((file: string) => `${files}/${file}`)
268
+ const downloadManager = new FileDownloadManager(fileList, 5)
269
+ await downloadManager.start()
270
+ // await fetchFilesRecursively(files, BROWSER_FS_TOP_DIR, fileList)
271
+ await confirmFilesExist(fileList)
272
+ logger('[syncDbFiles] Files synced!')
273
+ }
@@ -0,0 +1,137 @@
1
+ import { EventObject, fromCallback } from 'xstate'
2
+ import { waitForEvent } from '@/events'
3
+ import {
4
+ FromCallbackInput,
5
+ HydrateExistingItemEvent,
6
+ ItemMachineContext,
7
+ } from '@/types'
8
+
9
+ export const hydrateExistingItem = fromCallback<
10
+ EventObject,
11
+ FromCallbackInput<ItemMachineContext<any>, HydrateExistingItemEvent>
12
+ >(({ sendBack, input: { event, context } }) => {
13
+ const { existingItem } = event!
14
+ const { seedUid, seedLocalId, ModelClass } = context
15
+
16
+ if (!ModelClass) {
17
+ throw new Error('ModelClass not found')
18
+ }
19
+
20
+ const modelName = ModelClass.originalConstructor.name
21
+
22
+ const _checkForItemOnAllItemsService = async (): Promise<boolean> => {
23
+ if (!existingItem.seedLocalId && !existingItem.seedUid) {
24
+ console.warn(
25
+ '[singleItemActors] [hydrateExistingItem] No seedLocalId or seedUid found on existingItem',
26
+ )
27
+ return false
28
+ }
29
+
30
+ if (!seedUid && !seedLocalId) {
31
+ return false
32
+ }
33
+
34
+ const results = await waitForEvent({
35
+ req: {
36
+ eventLabel: 'item.request',
37
+ data: {
38
+ modelName,
39
+ seedUid,
40
+ seedLocalId,
41
+ source: 'hydrateExistingItem',
42
+ },
43
+ },
44
+ res: {
45
+ eventLabel: `item.${modelName}.${seedLocalId}.response`,
46
+ },
47
+ })
48
+
49
+ return true
50
+
51
+ // return new Promise((resolve) => {
52
+ // const timeStart = Date.now()
53
+ //
54
+ // const interval = setInterval(() => {
55
+ // const timeElapsed = Date.now() - timeStart
56
+ // if (timeElapsed > 2000) {
57
+ // eventEmitter.emit('item.request', {
58
+ // modelName,
59
+ // versionUid,
60
+ // versionLocalId,
61
+ // source: 'hydrateExistingItem',
62
+ // })
63
+ // }
64
+ // if (timeElapsed > 30000) {
65
+ // clearInterval(interval)
66
+ // console.error(
67
+ // `[singleItemActors] [hydrateExistingItem] ${timeElapsed / 1000}s elapsed for ${modelName} ${versionLocalId}`,
68
+ // context,
69
+ // )
70
+ // eventEmitter.removeListener(
71
+ // `item.${modelName}.response`,
72
+ // handleItemRequestResponse,
73
+ // )
74
+ // resolve(false)
75
+ // }
76
+ // }, 500)
77
+
78
+ // const handleItemRequestResponse = (event) => {
79
+ // if (
80
+ // event.item &&
81
+ // ((event.item.versionLocalId &&
82
+ // event.item.versionLocalId === versionLocalId) ||
83
+ // (event.item.versionUid && event.item.versionUid === versionUid))
84
+ // ) {
85
+ // clearInterval(interval)
86
+ // eventEmitter.removeListener(
87
+ // `item.${modelName}.response`,
88
+ // handleItemRequestResponse,
89
+ // )
90
+ // resolve(true)
91
+ // }
92
+ // }
93
+ //
94
+ // eventEmitter.addListener(
95
+ // `item.${modelName}.response`,
96
+ // handleItemRequestResponse,
97
+ // )
98
+ //
99
+ // eventEmitter.emit('item.request', {
100
+ // modelName,
101
+ // versionUid,
102
+ // versionLocalId,
103
+ // source: 'hydrateExistingItem',
104
+ // })
105
+ // })
106
+
107
+ // if (existingItem.versionLocalId && !existingItem.versionLocalId) {
108
+ // console.log(
109
+ // `[singleItemActors] [hydrateExistingItem] versionLocalId: ${existingItem.versionLocalId} versionUid: ${existingItem.versionUid}`,
110
+ // )
111
+ //
112
+ // return true
113
+ // }
114
+ //
115
+ // console.log(
116
+ // `[singleItemActors] [hydrateExistingItem] versionLocalId: ${existingItem.versionLocalId} versionUid: ${existingItem.versionUid}`,
117
+ // )
118
+ // return true
119
+ }
120
+
121
+ _checkForItemOnAllItemsService().then((shouldContinue) => {
122
+ if (!shouldContinue) {
123
+ sendBack({ type: 'hydrateExistingItemFailure' })
124
+ return
125
+ }
126
+ // for (const [key, value] of Object.entries(existingItem)) {
127
+ // sendBack({
128
+ // type: 'updateValue',
129
+ // propertyName: key,
130
+ // propertyValue: value,
131
+ // source: 'db',
132
+ // })
133
+ // }
134
+
135
+ sendBack({ type: 'hydrateExistingItemSuccess' })
136
+ })
137
+ })
@@ -0,0 +1,270 @@
1
+ import { EventObject, fromCallback } from 'xstate'
2
+ import { and, eq, or, sql } from 'drizzle-orm'
3
+ import debug from 'debug'
4
+ import fs from '@zenfs/core'
5
+ import { metadata } from '@/seedSchema'
6
+ import { BaseDb } from '@/db/Db/BaseDb'
7
+ import { updateMetadata } from '@/db/write/updateMetadata'
8
+ import { FromCallbackInput } from '@/types/machines'
9
+ import { PropertyMachineContext } from '@/types/property'
10
+ import path from 'path'
11
+
12
+ const logger = debug('app:property:actors:hydrateFromDb')
13
+
14
+ export const hydrateFromDb = fromCallback<
15
+ EventObject,
16
+ FromCallbackInput<PropertyMachineContext, EventObject>
17
+ >(({ sendBack, input: { context } }) => {
18
+ const {
19
+ seedUid,
20
+ seedLocalId,
21
+ propertyName: propertyNameRaw,
22
+ propertyRecordSchema,
23
+ modelName,
24
+ } = context
25
+
26
+ let propertyName = propertyNameRaw
27
+
28
+ if (
29
+ propertyRecordSchema &&
30
+ propertyRecordSchema.ref &&
31
+ propertyRecordSchema.dataType === 'Relation' &&
32
+ !propertyNameRaw.endsWith('Id')
33
+ ) {
34
+ propertyName = propertyNameRaw + 'Id'
35
+ }
36
+
37
+ if (
38
+ propertyRecordSchema &&
39
+ propertyRecordSchema.ref &&
40
+ propertyRecordSchema.dataType === 'List' &&
41
+ !propertyNameRaw.endsWith('Ids')
42
+ ) {
43
+ propertyName = propertyNameRaw + 'Ids'
44
+ }
45
+
46
+ const _hydrateFromDb = async () => {
47
+ const appDb = BaseDb.getAppDb()
48
+
49
+ const isRelation =
50
+ propertyRecordSchema &&
51
+ propertyRecordSchema.ref &&
52
+ propertyRecordSchema.dataType === 'Relation'
53
+
54
+ const whereClauses = []
55
+
56
+ if (isRelation) {
57
+ let missingPropertyNameVariant
58
+ if (propertyName.endsWith('Id')) {
59
+ missingPropertyNameVariant = propertyName.slice(0, -2)
60
+ }
61
+ if (!propertyName.endsWith('Id')) {
62
+ missingPropertyNameVariant = propertyName + 'Id'
63
+ }
64
+ if (missingPropertyNameVariant) {
65
+ whereClauses.push(
66
+ or(
67
+ eq(metadata.propertyName, propertyName),
68
+ eq(metadata.propertyName, missingPropertyNameVariant),
69
+ ),
70
+ )
71
+ }
72
+ if (!missingPropertyNameVariant) {
73
+ whereClauses.push(eq(metadata.propertyName, propertyName))
74
+ }
75
+ } else {
76
+ whereClauses.push(eq(metadata.propertyName, propertyName))
77
+ }
78
+
79
+ if (seedUid) {
80
+ whereClauses.push(eq(metadata.seedUid, seedUid))
81
+ }
82
+
83
+ if (seedLocalId) {
84
+ whereClauses.push(eq(metadata.seedLocalId, seedLocalId))
85
+ }
86
+
87
+ const rows = await appDb
88
+ .select()
89
+ .from(metadata)
90
+ .where(and(...whereClauses))
91
+ .orderBy(sql.raw('COALESCE(attestation_created_at, created_at) DESC'))
92
+
93
+ if (!rows || !rows.length) {
94
+ return
95
+ }
96
+
97
+ const firstRow = rows[0]
98
+
99
+ const {
100
+ localId,
101
+ uid,
102
+ propertyName: propertyNameFromDb,
103
+ propertyValue: propertyValueFromDb,
104
+ seedLocalId: seedLocalIdFromDb,
105
+ seedUid: seedUidFromDb,
106
+ schemaUid: schemaUidFromDb,
107
+ versionLocalId: versionLocalIdFromDb,
108
+ versionUid: versionUidFromDb,
109
+ refValueType,
110
+ localStorageDir,
111
+ } = firstRow
112
+
113
+ let { refResolvedDisplayValue, refResolvedValue } = firstRow
114
+
115
+ let propertyValueProcessed: string | string[] | undefined | null =
116
+ propertyValueFromDb
117
+
118
+
119
+ if (
120
+ propertyRecordSchema &&
121
+ propertyRecordSchema.refValueType === 'ImageSrc'
122
+ ) {
123
+ let shouldReadFromFile = true
124
+
125
+ if (
126
+ refResolvedValue &&
127
+ refResolvedDisplayValue &&
128
+ refResolvedDisplayValue.includes('http')
129
+ ) {
130
+ try {
131
+ const response = await fetch(refResolvedDisplayValue, {
132
+ method: 'HEAD',
133
+ })
134
+
135
+ // Check if the status is in the 200-299 range
136
+ if (response.ok) {
137
+ shouldReadFromFile = false
138
+ }
139
+ } catch (error) {
140
+ shouldReadFromFile = true
141
+ }
142
+ }
143
+
144
+ if (shouldReadFromFile) {
145
+ let dir = localStorageDir
146
+ if (
147
+ !dir &&
148
+ propertyRecordSchema &&
149
+ propertyRecordSchema.refValueType === 'ImageSrc'
150
+ ) {
151
+ dir = 'images'
152
+ }
153
+
154
+ dir = dir!.replace(/^\//, '')
155
+
156
+ if (
157
+ !refResolvedValue &&
158
+ propertyValueFromDb &&
159
+ propertyValueFromDb.length === 66
160
+ ) {
161
+ // Here the storageTransactionId is stored on a different record and
162
+ // we want to add it as the refResolvedValue
163
+ const storageTransactionQuery = await appDb
164
+ .select({
165
+ propertyValue: metadata.propertyValue,
166
+ })
167
+ .from(metadata)
168
+ .where(
169
+ and(
170
+ eq(metadata.seedUid, propertyValueFromDb),
171
+ or(
172
+ eq(metadata.propertyName, 'storageTransactionId'),
173
+ eq(metadata.propertyName, 'transactionId'),
174
+ ),
175
+ ),
176
+ )
177
+
178
+ if (storageTransactionQuery && storageTransactionQuery.length > 0) {
179
+ const row = storageTransactionQuery[0]
180
+ refResolvedValue = row.propertyValue
181
+ await updateMetadata({
182
+ localId,
183
+ refResolvedValue,
184
+ localStorageDir: '/images',
185
+ })
186
+ }
187
+ }
188
+
189
+ const dirPath = `/files/${dir}`
190
+ const files = await fs.promises.readdir(dirPath)
191
+ const matchingFiles = files.filter((file) => {
192
+ return path.basename(file).includes(refResolvedValue!)
193
+ })
194
+ let fileExists = false
195
+ let filename
196
+ let filePath
197
+ if (matchingFiles && matchingFiles.length > 0) {
198
+ fileExists = true
199
+ filename = matchingFiles[0]
200
+ filePath = `/files/${dir}/${filename}`
201
+ }
202
+ if (fileExists && filename && filePath) {
203
+ const fileContents = await fs.promises.readFile(filePath)
204
+ const fileHandler = new File([fileContents], filename)
205
+ refResolvedDisplayValue = URL.createObjectURL(fileHandler)
206
+ await updateMetadata({
207
+ localId,
208
+ refResolvedValue: filename,
209
+ })
210
+ }
211
+ }
212
+ }
213
+
214
+ if (
215
+ propertyRecordSchema &&
216
+ propertyRecordSchema.dataType === 'List' &&
217
+ propertyRecordSchema.ref &&
218
+ typeof propertyValueFromDb === 'string'
219
+ ) {
220
+ propertyValueProcessed = propertyValueFromDb.split(',')
221
+ }
222
+
223
+ sendBack({
224
+ type: 'updateContext',
225
+ localId,
226
+ uid,
227
+ propertyValue: propertyValueProcessed,
228
+ seedLocalId: seedLocalIdFromDb,
229
+ seedUid: seedUidFromDb,
230
+ versionLocalId: versionLocalIdFromDb,
231
+ versionUid: versionUidFromDb,
232
+ schemaUid: schemaUidFromDb,
233
+ refValueType,
234
+ localStorageDir,
235
+ refResolvedValue,
236
+ refResolvedDisplayValue,
237
+ renderValue: refResolvedDisplayValue,
238
+ populatedFromDb: true,
239
+ })
240
+
241
+ if (
242
+ propertyRecordSchema &&
243
+ propertyRecordSchema.storageType &&
244
+ propertyRecordSchema.storageType === 'ItemStorage'
245
+ ) {
246
+ const { Item } = await import(`@/browser/Item`)
247
+ const item = await Item.find({
248
+ seedLocalId,
249
+ modelName,
250
+ })
251
+ if (item) {
252
+ const filePath = `/files/${localStorageDir}/${refResolvedValue}`
253
+ const exists = await fs.promises.exists(filePath)
254
+
255
+ if (!exists) {
256
+ return
257
+ }
258
+
259
+ const renderValue = await fs.promises.readFile(filePath, 'utf8')
260
+ const property = item.properties[propertyName]
261
+ property.getService().send({ type: 'updateContext', renderValue })
262
+ return
263
+ }
264
+ }
265
+ }
266
+
267
+ _hydrateFromDb().then(() => {
268
+ sendBack({ type: 'hydrateFromDbSuccess' })
269
+ })
270
+ })
@@ -0,0 +1,34 @@
1
+ import { EventObject, fromCallback } from 'xstate'
2
+ import { createSeed } from '@/db/write/createSeed'
3
+ import { FromCallbackInput, ItemMachineContext } from '@/types'
4
+ import { createVersion } from '@/db/write/createVersion'
5
+
6
+ export const hydrateNewItem = fromCallback<
7
+ EventObject,
8
+ FromCallbackInput<ItemMachineContext<any>>
9
+ >(({ sendBack, input: { context } }) => {
10
+ const { seedUid, versionUid, modelName } = context
11
+
12
+ let newSeedLocalId: string
13
+
14
+ const _hydrateNewItem = async (): Promise<void> => {
15
+ if (!modelName) {
16
+ throw new Error('modelName is required')
17
+ }
18
+
19
+ newSeedLocalId = await createSeed({
20
+ type: modelName.toLowerCase(),
21
+ seedUid: seedUid ?? 'NULL',
22
+ })
23
+
24
+ await createVersion({
25
+ seedLocalId: newSeedLocalId,
26
+ seedType: modelName.toLowerCase(),
27
+ uid: versionUid ?? 'NULL',
28
+ })
29
+ }
30
+
31
+ _hydrateNewItem().then(() => {
32
+ sendBack({ type: 'hydrateNewItemSuccess' })
33
+ })
34
+ })