@seedprotocol/sdk 0.1.46 → 0.1.48

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 (147) hide show
  1. package/dist/bin.js.map +1 -1
  2. package/dist/constants-BLctWkrn.js.map +1 -1
  3. package/dist/{index-BEzB8REh.js → index-DMIKRod-.js} +3684 -3660
  4. package/dist/index-DMIKRod-.js.map +1 -0
  5. package/dist/{index-ChGsdGPJ.js → index-wKss7188.js} +10 -10
  6. package/dist/index-wKss7188.js.map +1 -0
  7. package/dist/main.js +7 -7
  8. package/dist/{seed.schema.config-jKpK-lR6.js → seed.schema.config-C0M8Rcti.js} +7 -7
  9. package/dist/seed.schema.config-C0M8Rcti.js.map +1 -0
  10. package/dist/src/AppStateSchema.ts +10 -0
  11. package/dist/src/Attestation.ts +21 -0
  12. package/dist/src/ConfigSchema.ts +15 -0
  13. package/dist/src/ItemProperty.ts +383 -0
  14. package/dist/src/MetadataSchema.ts +28 -0
  15. package/dist/src/ModelSchema.ts +46 -0
  16. package/dist/src/ModelUidSchema.ts +16 -0
  17. package/dist/src/PropertyUidSchema.ts +16 -0
  18. package/dist/src/Schema.ts +17 -0
  19. package/dist/src/SeedSchema.ts +29 -0
  20. package/dist/src/VersionSchema.ts +16 -0
  21. package/dist/src/actors.ts +10 -0
  22. package/dist/src/addModelsToDb.ts +150 -0
  23. package/dist/src/allItems.ts +23 -0
  24. package/dist/src/arweave.ts +37 -0
  25. package/dist/src/browser.app.db.config.ts +27 -0
  26. package/dist/src/browser.seed.db.config.ts +33 -0
  27. package/dist/src/browser.ts +30 -0
  28. package/dist/src/checkStatus.ts +50 -0
  29. package/dist/src/client.ts +85 -0
  30. package/dist/src/configureFs.ts +81 -0
  31. package/dist/src/connectToDb.ts +74 -0
  32. package/dist/src/connectionManager.ts +67 -0
  33. package/dist/src/constants.ts +118 -0
  34. package/dist/src/create.ts +39 -0
  35. package/dist/src/createItem.ts +15 -0
  36. package/dist/src/createItemMachine.ts +37 -0
  37. package/dist/src/createPublishAttempt.ts +16 -0
  38. package/dist/src/createSeeds.ts +24 -0
  39. package/dist/src/createVersion.ts +33 -0
  40. package/dist/src/db.ts +247 -0
  41. package/dist/src/dbMachine.ts +181 -0
  42. package/dist/src/deleteItem.ts +19 -0
  43. package/dist/src/download.ts +289 -0
  44. package/dist/src/drizzle.ts +82 -0
  45. package/dist/src/environment.ts +15 -0
  46. package/dist/src/eventBus.ts +5 -0
  47. package/dist/src/events.ts +14 -0
  48. package/dist/src/fetchDataFromEas.ts +90 -0
  49. package/dist/src/fetchDbData.ts +16 -0
  50. package/dist/src/fetchRelatedItems.ts +179 -0
  51. package/dist/src/fetchSeeds.ts +44 -0
  52. package/dist/src/fetchVersions.ts +41 -0
  53. package/dist/src/files.ts +16 -0
  54. package/dist/src/fragment-masking.ts +87 -0
  55. package/dist/src/fsProxy.ts +36 -0
  56. package/dist/src/getItem.ts +189 -0
  57. package/dist/src/getItemProperties.ts +162 -0
  58. package/dist/src/getItems.ts +75 -0
  59. package/dist/src/getMetadata.ts +40 -0
  60. package/dist/src/getModelSchemas.ts +88 -0
  61. package/dist/src/getSchemaForModel.ts +42 -0
  62. package/dist/src/getSeedData.ts +34 -0
  63. package/dist/src/getVersionData.ts +58 -0
  64. package/dist/src/getVersionsForVersionUids.ts +39 -0
  65. package/dist/src/globalMachine.ts +259 -0
  66. package/dist/src/gql.ts +113 -0
  67. package/dist/src/graphql.ts +3201 -0
  68. package/dist/src/helpers.ts +150 -0
  69. package/dist/src/hydrateExistingItem.ts +137 -0
  70. package/dist/src/hydrateFromDb.ts +254 -0
  71. package/dist/src/hydrateNewItem.ts +34 -0
  72. package/dist/src/index.d.ts +5 -0
  73. package/dist/src/index.ts +21 -0
  74. package/dist/src/init.ts +61 -0
  75. package/dist/src/initialize.ts +127 -0
  76. package/dist/src/internalMachine.ts +220 -0
  77. package/dist/src/item.ts +324 -0
  78. package/dist/src/itemMachineAll.ts +158 -0
  79. package/dist/src/itemMachineSingle.ts +175 -0
  80. package/dist/src/loadAppDb.ts +47 -0
  81. package/dist/src/logger.ts +33 -0
  82. package/dist/src/machine.ts +55 -0
  83. package/dist/src/machines.ts +58 -0
  84. package/dist/src/migrate.ts +288 -0
  85. package/dist/src/model.ts +71 -0
  86. package/dist/src/modelClass.ts +19 -0
  87. package/dist/src/node.app.db.config.ts +40 -0
  88. package/dist/src/prepareDb.ts +34 -0
  89. package/dist/src/preparePublishRequestData.ts +81 -0
  90. package/dist/src/processItems.ts +71 -0
  91. package/dist/src/property.ts +161 -0
  92. package/dist/src/propertyMachine.ts +154 -0
  93. package/dist/src/publish.ts +31 -0
  94. package/dist/src/publishMachine.ts +77 -0
  95. package/dist/src/queries.ts +13 -0
  96. package/dist/src/read.ts +174 -0
  97. package/dist/src/recoverDeletedItem.ts +14 -0
  98. package/dist/src/request.ts +54 -0
  99. package/dist/src/requestAll.ts +157 -0
  100. package/dist/src/resolveRelatedValue.ts +348 -0
  101. package/dist/src/resolveRemoteStorage.ts +87 -0
  102. package/dist/src/save.ts +183 -0
  103. package/dist/src/saveConfig.ts +79 -0
  104. package/dist/src/saveDataToDb.ts +145 -0
  105. package/dist/src/saveMetadata.ts +18 -0
  106. package/dist/src/saveValueToDb.ts +94 -0
  107. package/dist/src/seed.schema.config.ts +25 -0
  108. package/dist/src/seed.ts +37 -0
  109. package/dist/src/seedData.ts +0 -0
  110. package/dist/src/seedProtocol.ts +17 -0
  111. package/dist/src/services.ts +359 -0
  112. package/dist/src/sqlWasmClient.ts +88 -0
  113. package/dist/src/syncDbWithEas.ts +686 -0
  114. package/dist/src/trash.ts +29 -0
  115. package/dist/src/ts-to-proto.ts +101 -0
  116. package/dist/src/types.ts +12 -0
  117. package/dist/src/upload.ts +86 -0
  118. package/dist/src/validate.ts +42 -0
  119. package/dist/src/validateInput.ts +33 -0
  120. package/dist/src/validateItemData.ts +20 -0
  121. package/dist/src/waitForDb.ts +23 -0
  122. package/dist/src/wasm.d.ts +8300 -0
  123. package/dist/src/write.ts +366 -0
  124. package/dist/types/src/browser/db/read/getModelSchemas.d.ts.map +1 -1
  125. package/dist/types/src/browser/events/item/create.d.ts.map +1 -1
  126. package/dist/types/src/browser/events/item/publish.d.ts.map +1 -1
  127. package/dist/types/src/browser/events/item/requestAll.d.ts.map +1 -1
  128. package/dist/types/src/browser/events/item/syncDbWithEas.d.ts.map +1 -1
  129. package/dist/types/src/browser/item/single/actors/hydrateExistingItem.d.ts +3 -1
  130. package/dist/types/src/browser/item/single/actors/hydrateExistingItem.d.ts.map +1 -1
  131. package/dist/types/src/browser/item/single/actors/saveDataToDb.d.ts +3 -3
  132. package/dist/types/src/browser/item/single/itemMachineSingle.d.ts +3 -3
  133. package/dist/types/src/browser/property/ItemProperty.d.ts +7 -7
  134. package/dist/types/src/browser/property/ItemProperty.d.ts.map +1 -1
  135. package/dist/types/src/browser/property/actors/hydrateFromDb.d.ts.map +1 -1
  136. package/dist/types/src/browser/property/actors/initialize.d.ts.map +1 -1
  137. package/dist/types/src/browser/property/actors/resolveRemoteStorage.d.ts +3 -3
  138. package/dist/types/src/browser/react/trash.d.ts +1 -1
  139. package/dist/types/src/browser/react/trash.d.ts.map +1 -1
  140. package/dist/types/src/browser/services/db/dbMachine.d.ts +6 -6
  141. package/dist/types/src/browser/services/publish/publishMachine.d.ts +17 -17
  142. package/dist/types/src/types/machines.d.ts +4 -0
  143. package/dist/types/src/types/machines.d.ts.map +1 -1
  144. package/package.json +1 -1
  145. package/dist/index-BEzB8REh.js.map +0 -1
  146. package/dist/index-ChGsdGPJ.js.map +0 -1
  147. package/dist/seed.schema.config-jKpK-lR6.js.map +0 -1
@@ -0,0 +1,686 @@
1
+ import { camelCase, debounce, DebouncedFunc, startCase } from 'lodash-es'
2
+ import { Attestation, SchemaWhereInput } from '@/browser/gql/graphql'
3
+ import {
4
+ metadata,
5
+ MetadataType,
6
+ modelUids,
7
+ properties,
8
+ propertyUids,
9
+ seeds,
10
+ SeedType,
11
+ versions,
12
+ } from '@/shared/seedSchema'
13
+ import { and, eq, inArray, sql } from 'drizzle-orm'
14
+ import {
15
+ generateId,
16
+ parseEasRelationPropertyName,
17
+ toSnakeCase,
18
+ } from '@/shared/helpers'
19
+ import { easClient, queryClient } from '@/browser/helpers'
20
+ import {
21
+ GET_PROPERTIES,
22
+ GET_SCHEMAS,
23
+ GET_SEEDS,
24
+ GET_VERSIONS,
25
+ } from '@/browser/item/queries'
26
+ import { INTERNAL_DATA_TYPES } from '@/shared/helpers/constants'
27
+ import { escapeSqliteString, getAddressesFromDb } from '@/shared/helpers/db'
28
+ import { eventEmitter } from '@/eventBus'
29
+ import { getModelNames, getModels } from '@/browser/stores/modelClass'
30
+ import { getAppDb } from '@/browser/db/sqlWasmClient'
31
+ import { getModelSchemas } from '@/browser/db/read/getModelSchemas'
32
+ import debug from 'debug'
33
+ import { ModelSchema, PropertyType } from '@/types'
34
+ import { createSeeds } from '@/browser/db/write/createSeeds'
35
+
36
+ const logger = debug('app:item:events:syncDbWithEas')
37
+
38
+ const relationValuesToExclude = [
39
+ '0x0000000000000000000000000000000000000000000000000000000000000020',
40
+ ]
41
+
42
+ const processPropertiesFoundInDb = async ({ foundModel }) => {
43
+ const appDb = getAppDb()
44
+
45
+ const foundPropertiesDb = await appDb
46
+ .select({
47
+ id: properties.id,
48
+ name: properties.name,
49
+ dataType: properties.dataType,
50
+ uid: propertyUids.uid,
51
+ })
52
+ .from(properties)
53
+ .fullJoin(propertyUids, eq(properties.id, propertyUids.propertyId))
54
+ .where(eq(properties.modelId, foundModel.id))
55
+
56
+ if (!foundPropertiesDb || foundPropertiesDb.length === 0) {
57
+ return
58
+ }
59
+
60
+ if (foundPropertiesDb && foundPropertiesDb.length > 0) {
61
+ const queryVariables: { where: SchemaWhereInput } = {
62
+ where: {
63
+ OR: [],
64
+ },
65
+ }
66
+
67
+ for (const foundPropertyDb of foundPropertiesDb) {
68
+ if (foundPropertyDb.name && foundPropertyDb.dataType) {
69
+ const easDatatype = INTERNAL_DATA_TYPES[foundPropertyDb.dataType].eas
70
+
71
+ let easPropertyName = toSnakeCase(foundPropertyDb.name)
72
+
73
+ if (foundPropertyDb.dataType === 'Relation') {
74
+ easPropertyName += '_id'
75
+ }
76
+
77
+ queryVariables.where.OR!.push({
78
+ schema: {
79
+ equals: `${easDatatype} ${easPropertyName}`,
80
+ },
81
+ })
82
+ }
83
+ }
84
+
85
+ const modelName = foundModel.name
86
+
87
+ const foundPropertySchemas = await queryClient.fetchQuery({
88
+ queryKey: [`getPropertySchemas${modelName}`],
89
+ queryFn: async () => easClient.request(GET_SCHEMAS, queryVariables),
90
+ })
91
+
92
+ const tempExclusions = ['html', 'json']
93
+
94
+ for (const foundProperty of foundPropertiesDb) {
95
+ if (tempExclusions.includes(foundProperty.name)) {
96
+ continue
97
+ }
98
+ const easDatatype = INTERNAL_DATA_TYPES[foundProperty.dataType].eas
99
+
100
+ let easPropertyName = toSnakeCase(foundProperty.name)
101
+
102
+ if (foundProperty.dataType === 'Relation') {
103
+ easPropertyName += '_id'
104
+ }
105
+
106
+ const regex = new RegExp(`${easDatatype} ${easPropertyName}`)
107
+ const propertySchema = foundPropertySchemas.schemas.find((s) =>
108
+ regex.test(s.schema),
109
+ )
110
+
111
+ if (!propertySchema) {
112
+ // TODO: We should create the schema here?
113
+ continue
114
+ }
115
+ await appDb
116
+ .insert(propertyUids)
117
+ .values({
118
+ propertyId: foundProperty.id,
119
+ uid: propertySchema.id,
120
+ })
121
+ .onConflictDoNothing()
122
+ }
123
+ }
124
+ }
125
+
126
+ const getSeedsFromSchemaUids = async ({ schemaUids, addresses }) => {
127
+ const AND = [
128
+ {
129
+ OR: [] as Record<string, unknown>[],
130
+ },
131
+ ]
132
+
133
+ for (const schemaUid of schemaUids) {
134
+ AND[0].OR.push({
135
+ decodedDataJson: {
136
+ contains: schemaUid,
137
+ },
138
+ })
139
+ }
140
+
141
+ const { itemSeeds } = await queryClient.fetchQuery({
142
+ queryKey: [`getSeedsForAllModels`],
143
+ queryFn: async () =>
144
+ easClient.request(GET_SEEDS, {
145
+ where: {
146
+ attester: {
147
+ in: addresses,
148
+ },
149
+ schemaId: {
150
+ in: schemaUids,
151
+ },
152
+ AND,
153
+ },
154
+ }),
155
+ })
156
+
157
+ return itemSeeds
158
+ }
159
+
160
+ const seedUidToLocalId = new Map<string, string>()
161
+ const seedUidToModelType = new Map<string, string>()
162
+ const relatedSeedUids = new Set<string>()
163
+
164
+ const versionUidToLocalId = new Map<string, string>()
165
+ const versionUidToSeedUid = new Map<string, string>()
166
+
167
+ const propertyUidToLocalId = new Map<string, string>()
168
+
169
+ type SaveEasSeedsToDbProps = {
170
+ itemSeeds: Attestation[]
171
+ }
172
+
173
+ type SaveEasSeedsToDbReturn = {
174
+ seedUids: string[]
175
+ }
176
+
177
+ type SaveEasSeedsToDb = (
178
+ props: SaveEasSeedsToDbProps,
179
+ ) => Promise<SaveEasSeedsToDbReturn>
180
+
181
+ const saveEasSeedsToDb: SaveEasSeedsToDb = async ({ itemSeeds }) => {
182
+ const appDb = getAppDb()
183
+
184
+ const seedUids = itemSeeds.map((seed) => seed.id)
185
+
186
+ const existingSeedRecordsRows: SeedType[] = await appDb
187
+ .select()
188
+ .from(seeds)
189
+ .where(inArray(seeds.uid, seedUids))
190
+
191
+ const existingSeedUids = new Set<string>()
192
+
193
+ if (existingSeedRecordsRows && existingSeedRecordsRows.length > 0) {
194
+ for (const row of existingSeedRecordsRows) {
195
+ existingSeedUids.add(row.uid)
196
+ seedUidToLocalId.set(row.uid, row.localId)
197
+ }
198
+ }
199
+
200
+ const newSeeds = itemSeeds.filter((seed) => !existingSeedUids.has(seed.id))
201
+
202
+ if (newSeeds.length === 0) {
203
+ return { seedUidToLocalId, seedUids }
204
+ }
205
+
206
+ const newSeedsData: Partial<SeedType>[] = []
207
+
208
+ for (let i = 0; i < newSeeds.length; i++) {
209
+ const seed = newSeeds[i]
210
+ seedUidToModelType.set(seed.id, seed.schema.schemaNames[0].name)
211
+ const seedLocalId = generateId()
212
+ seedUidToLocalId.set(seed.id, seedLocalId)
213
+
214
+ const attestationRaw = escapeSqliteString(JSON.stringify(seed))
215
+
216
+ newSeedsData.push({
217
+ localId: seedLocalId,
218
+ uid: seed.id,
219
+ schemaUid: seed.schemaId,
220
+ type: seed.schema.schemaNames[0].name,
221
+ createdAt: Date.now(),
222
+ attestationCreatedAt: seed.timeCreated * 1000,
223
+ attestationRaw,
224
+ })
225
+
226
+ seedUidToLocalId.set(seed.id, seedLocalId)
227
+ }
228
+
229
+ const newSeedUids = await createSeeds(newSeedsData)
230
+
231
+ return { seedUids: newSeedUids }
232
+ }
233
+
234
+ type SaveEasVersionsToDbParams = {
235
+ itemVersions: Attestation[]
236
+ }
237
+
238
+ type SaveEasVersionsToDb = (
239
+ props: SaveEasVersionsToDbParams,
240
+ ) => Promise<Record<string, unknown>>
241
+
242
+ const saveEasVersionsToDb: SaveEasVersionsToDb = async ({ itemVersions }) => {
243
+ const versionUids = itemVersions.map((version) => version.id)
244
+
245
+ const appDb = getAppDb()
246
+
247
+ const existingVersionRecordsRows: MetadataType[] = await appDb
248
+ .select()
249
+ .from(versions)
250
+ .where(inArray(versions.uid, versionUids))
251
+
252
+ const existingVersionUids = new Set<string>()
253
+
254
+ if (existingVersionRecordsRows && existingVersionRecordsRows.length > 0) {
255
+ for (const row of existingVersionRecordsRows) {
256
+ existingVersionUids.add(row.uid)
257
+ versionUidToLocalId.set(row.uid, row.localId)
258
+ }
259
+ }
260
+
261
+ const newVersions = itemVersions.filter(
262
+ (version) => !existingVersionUids.has(version.id),
263
+ )
264
+
265
+ if (newVersions.length === 0) {
266
+ return { versionUidToLocalId, versionUids }
267
+ }
268
+
269
+ let insertVersionsQuery = `INSERT INTO versions (local_id, uid, seed_uid, seed_local_id, seed_type, created_at,
270
+ attestation_created_at,
271
+ attestation_raw)
272
+ VALUES `
273
+
274
+ for (let i = 0; i < newVersions.length; i++) {
275
+ const version = newVersions[i]
276
+ versionUidToSeedUid.set(version.id, version.refUID)
277
+ const versionLocalId = generateId()
278
+ versionUidToLocalId.set(version.id, versionLocalId)
279
+
280
+ const seedUid = versionUidToSeedUid.get(version.id)
281
+ const seedLocalId = seedUidToLocalId.get(seedUid!)
282
+ const seedType = seedUidToModelType.get(seedUid!)
283
+ const attestationRaw = escapeSqliteString(JSON.stringify(version))
284
+
285
+ const valuesString = `('${versionLocalId}', '${version.id}', '${seedUid}', '${seedLocalId}', '${seedType}', ${Date.now()}, ${version.timeCreated * 1000}, '${attestationRaw}')`
286
+
287
+ if (i < newVersions.length - 1) {
288
+ insertVersionsQuery += valuesString + ', '
289
+ }
290
+
291
+ if (i === newVersions.length - 1) {
292
+ insertVersionsQuery += valuesString + ';'
293
+ }
294
+
295
+ versionUidToLocalId.set(version.id, versionLocalId)
296
+ }
297
+
298
+ await appDb.run(sql.raw(insertVersionsQuery))
299
+
300
+ return { versionUids }
301
+ }
302
+
303
+ const createMetadataRecordsForStorageTransactionId = async (
304
+ storageTransactionIdProperty: Attestation,
305
+ modelSchema: ModelSchema,
306
+ ) => {
307
+ const attestationData = JSON.parse(
308
+ storageTransactionIdProperty.decodedDataJson,
309
+ )[0].value
310
+ const propertyName = camelCase(attestationData.name)
311
+ const propertyValue = attestationData.value
312
+
313
+ const itemStorageProperties = new Map<string, PropertyType>()
314
+
315
+ for (const [_propertyName, propertyDef] of Object.entries(modelSchema)) {
316
+ if (propertyDef?.storageType && propertyDef.storageType === 'ItemStorage') {
317
+ itemStorageProperties.set(_propertyName, propertyDef)
318
+ }
319
+ }
320
+
321
+ if (itemStorageProperties.size === 0) {
322
+ return
323
+ }
324
+
325
+ const appDb = getAppDb()
326
+
327
+ for (const [_propertyName, propertyDef] of itemStorageProperties.entries()) {
328
+ const existingMetadataRecordRows = await appDb
329
+ .select()
330
+ .from(metadata)
331
+ .where(
332
+ and(
333
+ eq(metadata.propertyName, _propertyName),
334
+ eq(metadata.propertyValue, propertyValue),
335
+ eq(metadata.versionUid, storageTransactionIdProperty.refUID),
336
+ ),
337
+ )
338
+
339
+ if (existingMetadataRecordRows && existingMetadataRecordRows.length > 0) {
340
+ continue
341
+ }
342
+
343
+ const seedUid = versionUidToSeedUid.get(
344
+ storageTransactionIdProperty.refUID,
345
+ ) as string
346
+ const seedLocalId = seedUidToLocalId.get(seedUid)
347
+ const versionUid = storageTransactionIdProperty.refUID
348
+ const versionLocalId = versionUidToLocalId.get(versionUid)
349
+
350
+ const propertyLocalId = generateId()
351
+ await appDb.insert(metadata).values({
352
+ localId: propertyLocalId,
353
+ propertyName: _propertyName,
354
+ propertyValue,
355
+ localStorageDir: propertyDef.localStorageDir,
356
+ seedLocalId,
357
+ seedUid,
358
+ versionLocalId,
359
+ versionUid,
360
+ refValueType: 'file',
361
+ refResolvedValue: `${propertyValue}.${propertyDef.filenameSuffix}`,
362
+ modelType: seedUidToModelType.get(seedUid),
363
+ createdAt: Date.now(),
364
+ updatedAt: Date.now(),
365
+ })
366
+ }
367
+ }
368
+
369
+ type SaveEasPropertiesToDbParams = {
370
+ itemProperties: Attestation[]
371
+ itemSeeds: Attestation[]
372
+ }
373
+
374
+ type SaveEasPropertiesToDb = (
375
+ props: SaveEasPropertiesToDbParams,
376
+ ) => Promise<Record<string, unknown>>
377
+
378
+ const saveEasPropertiesToDb: SaveEasPropertiesToDb = async ({
379
+ itemProperties,
380
+ itemSeeds,
381
+ }) => {
382
+ const propertyUids = itemProperties.map((property) => property.id)
383
+
384
+ const models = getModels()
385
+
386
+ const appDb = getAppDb()
387
+
388
+ const existingMetadataRecordsRows: MetadataType[] = await appDb
389
+ .select()
390
+ .from(metadata)
391
+ .where(inArray(metadata.uid, propertyUids))
392
+
393
+ const existingPropertyRecordsUids = new Set<string>()
394
+
395
+ if (existingMetadataRecordsRows && existingMetadataRecordsRows.length > 0) {
396
+ for (const row of existingMetadataRecordsRows) {
397
+ existingPropertyRecordsUids.add(row.uid)
398
+ propertyUidToLocalId.set(row.uid, row.localId)
399
+ }
400
+ }
401
+
402
+ const newProperties = itemProperties.filter(
403
+ (property) => !existingPropertyRecordsUids.has(property.id),
404
+ )
405
+
406
+ if (newProperties.length === 0) {
407
+ return { propertyUidToLocalId, propertyUids }
408
+ }
409
+
410
+ let insertPropertiesQuery = `INSERT INTO metadata (local_id, uid, schema_uid, property_name, property_value,
411
+ eas_data_type, version_uid, version_local_id, seed_uid,
412
+ seed_local_id, model_type, ref_value_type, ref_seed_type,
413
+ created_at, attestation_created_at, attestation_raw,
414
+ local_storage_dir, ref_resolved_value)
415
+ VALUES `
416
+
417
+ for (let i = 0; i < newProperties.length; i++) {
418
+ const property = newProperties[i]
419
+ const propertyLocalId = generateId()
420
+ const metadata = JSON.parse(property.decodedDataJson)[0].value
421
+
422
+ let propertyNameSnake = metadata.name
423
+
424
+ if (!propertyNameSnake) {
425
+ propertyNameSnake = metadata.name
426
+ }
427
+
428
+ if (!propertyNameSnake) {
429
+ console.warn(
430
+ '[item/events] [syncDbWithEas] no propertyName found for property: ',
431
+ property,
432
+ )
433
+ return
434
+ }
435
+
436
+ let isRelation = false
437
+ let refValueType
438
+ let refSeedType
439
+ let refResolvedValue
440
+ let isList = false
441
+
442
+ if (
443
+ (propertyNameSnake.endsWith('_id') ||
444
+ propertyNameSnake.endsWith('_ids')) &&
445
+ propertyNameSnake !== 'storage_transaction_id' &&
446
+ propertyNameSnake !== 'storage_provider_transaction_id'
447
+ ) {
448
+ isRelation = true
449
+
450
+ if (Array.isArray(metadata.value)) {
451
+ isList = true
452
+ refValueType = 'list'
453
+
454
+ const result = parseEasRelationPropertyName(propertyNameSnake)
455
+
456
+ if (result) {
457
+ propertyNameSnake = result.propertyName
458
+ refSeedType = result.modelName
459
+ }
460
+
461
+ metadata.value.forEach((value) => {
462
+ relatedSeedUids.add(value)
463
+ })
464
+ }
465
+
466
+ if (!isList) {
467
+ if (relationValuesToExclude.includes(metadata.value)) {
468
+ continue
469
+ }
470
+ relatedSeedUids.add(metadata.value)
471
+ }
472
+ }
473
+
474
+ let propertyValue = metadata.value
475
+
476
+ if (typeof propertyValue !== 'string') {
477
+ propertyValue = JSON.stringify(propertyValue)
478
+ }
479
+
480
+ if (isRelation && !isList) {
481
+ const relatedSeed = itemSeeds.find(
482
+ (seed: Attestation) => seed.id === metadata.value,
483
+ )
484
+ if (relatedSeed && relatedSeed.schema && relatedSeed.schema.schemaNames) {
485
+ refSeedType = relatedSeed.schema.schemaNames[0].name
486
+ }
487
+ }
488
+
489
+ if (isRelation && isList) {
490
+ const relatedSeeds = itemSeeds.filter((seed: Attestation) =>
491
+ metadata.value.includes(seed.id),
492
+ )
493
+ if (relatedSeeds && relatedSeeds.length > 0) {
494
+ refSeedType = relatedSeeds[0].schema.schemaNames[0].name
495
+ }
496
+ }
497
+
498
+ const propertyName = camelCase(propertyNameSnake)
499
+ propertyValue = escapeSqliteString(propertyValue)
500
+ const easDataType = metadata.type
501
+ const versionUid = property.refUID
502
+ const versionLocalId = versionUidToLocalId.get(versionUid)
503
+ const attestationCreatedAt = property.timeCreated * 1000
504
+ const attestationRaw = escapeSqliteString(JSON.stringify(property))
505
+ const seedUid = versionUidToSeedUid.get(versionUid)
506
+ const seedLocalId = seedUidToLocalId.get(seedUid!)
507
+ const modelType = seedUidToModelType.get(seedUid!)
508
+
509
+ let localStorageDir
510
+ const modelName = startCase(modelType)
511
+ const ModelClass = models[modelName]
512
+ const modelSchema = ModelClass.schema
513
+
514
+ if (propertyNameSnake === 'storage_transaction_id') {
515
+ await createMetadataRecordsForStorageTransactionId(property, modelSchema)
516
+ }
517
+
518
+ const valuesString = `('${propertyLocalId}', '${property.id}',
519
+ '${property.schemaId}', '${propertyName}',
520
+ '${propertyValue}', '${easDataType}', '${versionUid}',
521
+ '${versionLocalId}', '${seedUid}', '${seedLocalId}',
522
+ '${modelType}', ${refValueType ? `'${refValueType}'` : 'NULL'},
523
+ ${refSeedType ? `'${refSeedType}'` : 'NULL'},
524
+ ${Date.now()}, ${attestationCreatedAt}, '${attestationRaw}',
525
+ ${localStorageDir ? `'${localStorageDir}'` : 'NULL'},
526
+ ${refResolvedValue ? `'${refResolvedValue}'` : 'NULL'})`
527
+
528
+ if (i < newProperties.length - 1) {
529
+ insertPropertiesQuery += valuesString + ', '
530
+ }
531
+
532
+ if (i === newProperties.length - 1) {
533
+ insertPropertiesQuery += valuesString + ';'
534
+ }
535
+
536
+ propertyUidToLocalId.set(property.id, propertyLocalId)
537
+ }
538
+
539
+ if (insertPropertiesQuery.endsWith('VALUES ')) {
540
+ return { propertyUids }
541
+ }
542
+
543
+ if (insertPropertiesQuery.endsWith(', ')) {
544
+ insertPropertiesQuery = insertPropertiesQuery.slice(0, -2) + ';'
545
+ }
546
+
547
+ await appDb.run(sql.raw(insertPropertiesQuery))
548
+
549
+ return { propertyUids }
550
+ }
551
+
552
+ const getRelatedSeedsAndVersions = async () => {
553
+ const { itemSeeds } = await easClient.request(GET_SEEDS, {
554
+ where: {
555
+ id: {
556
+ in: Array.from(relatedSeedUids),
557
+ },
558
+ },
559
+ })
560
+
561
+ await saveEasSeedsToDb({ itemSeeds })
562
+
563
+ const { itemVersions } = await easClient.request(GET_VERSIONS, {
564
+ where: {
565
+ refUID: {
566
+ in: Array.from(relatedSeedUids),
567
+ },
568
+ },
569
+ })
570
+
571
+ await saveEasVersionsToDb({ itemVersions })
572
+
573
+ const relatedVersionUids = itemVersions.map((v) => v.id)
574
+
575
+ const { itemProperties } = await easClient.request(GET_PROPERTIES, {
576
+ where: {
577
+ refUID: {
578
+ in: relatedVersionUids,
579
+ },
580
+ },
581
+ })
582
+
583
+ await saveEasPropertiesToDb({
584
+ itemProperties,
585
+ itemSeeds,
586
+ })
587
+ }
588
+
589
+ const syncDbWithEasHandler: DebouncedFunc<any> = debounce(
590
+ async (_) => {
591
+ const appDb = getAppDb()
592
+
593
+ const { modelSchemas, schemaStringToModelRecord } = await getModelSchemas()
594
+
595
+ if (
596
+ !modelSchemas ||
597
+ !modelSchemas.schemas ||
598
+ modelSchemas.schemas.length === 0
599
+ ) {
600
+ throw new Error(`No schemas found for models`)
601
+ }
602
+
603
+ const schemaUids: string[] = []
604
+
605
+ for (const modelSchema of modelSchemas.schemas) {
606
+ const foundModel = schemaStringToModelRecord.get(modelSchema.schema)
607
+
608
+ if (!foundModel) {
609
+ throw new Error(`Model not found for schema ${modelSchema.schema}`)
610
+ }
611
+
612
+ schemaUids.push(modelSchema.id)
613
+
614
+ await appDb
615
+ .insert(modelUids)
616
+ .values({
617
+ modelId: foundModel.id,
618
+ uid: modelSchema.id,
619
+ })
620
+ .onConflictDoNothing()
621
+
622
+ await processPropertiesFoundInDb({
623
+ foundModel,
624
+ })
625
+ }
626
+
627
+ const addresses = await getAddressesFromDb()
628
+
629
+ const itemSeeds = await getSeedsFromSchemaUids({
630
+ schemaUids: schemaUids,
631
+ addresses,
632
+ })
633
+
634
+ // const seedDbRecords = new Map<string, Record<string, unknown>>()
635
+
636
+ const { seedUids } = await saveEasSeedsToDb({
637
+ itemSeeds,
638
+ })
639
+
640
+ const { itemVersions } = await queryClient.fetchQuery({
641
+ queryKey: [`getVersionsForAllModels`],
642
+ queryFn: async () =>
643
+ easClient.request(GET_VERSIONS, {
644
+ where: {
645
+ refUID: {
646
+ in: seedUids,
647
+ },
648
+ },
649
+ }),
650
+ })
651
+
652
+ const { versionUids } = await saveEasVersionsToDb({
653
+ itemVersions,
654
+ })
655
+
656
+ const { itemProperties } = await queryClient.fetchQuery({
657
+ queryKey: [`getPropertiesForAllModels`],
658
+ queryFn: async () =>
659
+ easClient.request(GET_PROPERTIES, {
660
+ where: {
661
+ refUID: {
662
+ in: versionUids,
663
+ },
664
+ },
665
+ }),
666
+ })
667
+
668
+ const { propertyUids } = saveEasPropertiesToDb({
669
+ itemProperties,
670
+ itemSeeds,
671
+ })
672
+
673
+ await getRelatedSeedsAndVersions()
674
+
675
+ for (const modelName of getModelNames()) {
676
+ eventEmitter.emit('item.requestAll', { modelName })
677
+ }
678
+ },
679
+ 10000,
680
+ {
681
+ leading: true,
682
+ trailing: false,
683
+ },
684
+ )
685
+
686
+ export { syncDbWithEasHandler }
@@ -0,0 +1,29 @@
1
+ import { useCallback, useEffect, useState } from 'react'
2
+ import { Item } from '@/browser/item/Item'
3
+ import { eventEmitter } from '@/eventBus'
4
+ import { deleteItem } from '@/browser/db/write/deleteItem'
5
+
6
+ export const useDeleteItem = () => {
7
+ const [isDeletingItem, setIsDeletingItem] = useState(false)
8
+
9
+ const destroy = useCallback(
10
+ async (item: Item<any>) => {
11
+ if (!item) {
12
+ return
13
+ }
14
+ setIsDeletingItem(true)
15
+ const { modelName } = item.getService().getSnapshot().context
16
+ await deleteItem({ seedLocalId: item.seedLocalId })
17
+ eventEmitter.emit('item.requestAll', { modelName })
18
+ setIsDeletingItem(false)
19
+ },
20
+ [isDeletingItem],
21
+ )
22
+
23
+ useEffect(() => {}, [])
24
+
25
+ return {
26
+ deleteItem: destroy,
27
+ isDeletingItem,
28
+ }
29
+ }