@seedprotocol/sdk 0.2.48 → 0.2.50

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 (46) hide show
  1. package/dist/{Db-BhLWMUOe.js → Db-BwkMqaQe.js} +2 -2
  2. package/dist/Db-BwkMqaQe.js.map +1 -0
  3. package/dist/{Db-DrcygP77.js → Db-jJH2s0gO.js} +2 -2
  4. package/dist/{Db-DrcygP77.js.map → Db-jJH2s0gO.js.map} +1 -1
  5. package/dist/{Item-D0rGmrZg.js → Item-DI3FxVPV.js} +2 -2
  6. package/dist/{Item-D0rGmrZg.js.map → Item-DI3FxVPV.js.map} +1 -1
  7. package/dist/{ItemProperty-D0tkeKx1.js → ItemProperty-CxNUwVnR.js} +2 -2
  8. package/dist/{ItemProperty-D0tkeKx1.js.map → ItemProperty-CxNUwVnR.js.map} +1 -1
  9. package/dist/{index-B6FQruEq.js → index-CKrLHw3B.js} +56 -26
  10. package/dist/{index-B6FQruEq.js.map → index-CKrLHw3B.js.map} +1 -1
  11. package/dist/{index-C93o7-zP.js → index-Dv8GeuSw.js} +2 -2
  12. package/dist/index-Dv8GeuSw.js.map +1 -0
  13. package/dist/main.js +1 -1
  14. package/dist/{seed.schema.config-ClOsMOKS.js → seed.schema.config-1s-iWHq_.js} +2 -2
  15. package/dist/{seed.schema.config-ClOsMOKS.js.map → seed.schema.config-1s-iWHq_.js.map} +1 -1
  16. package/dist/src/BaseItem.ts +16 -3
  17. package/dist/src/BaseItemProperty.ts +2 -2
  18. package/dist/src/IItem.ts +4 -1
  19. package/dist/src/actors.ts +272 -34
  20. package/dist/src/client.ts +8 -2
  21. package/dist/src/createMetadata.ts +14 -9
  22. package/dist/src/createNewItem.ts +6 -2
  23. package/dist/src/saveImageSrc.ts +0 -4
  24. package/dist/src/saveItemStorage.ts +7 -1
  25. package/dist/src/updateMetadata.ts +41 -1
  26. package/dist/src/waitForDb.ts +9 -10
  27. package/dist/types/src/Item/BaseItem.d.ts +4 -1
  28. package/dist/types/src/Item/BaseItem.d.ts.map +1 -1
  29. package/dist/types/src/Item/service/actors/saveDataToDb.d.ts +3 -0
  30. package/dist/types/src/Item/service/actors/saveDataToDb.d.ts.map +1 -0
  31. package/dist/types/src/ItemProperty/service/actors/saveValueToDb/saveImageSrc.d.ts.map +1 -1
  32. package/dist/types/src/ItemProperty/service/actors/saveValueToDb/saveItemStorage.d.ts.map +1 -1
  33. package/dist/types/src/browser/db/Db.d.ts +1 -1
  34. package/dist/types/src/browser/db/Db.d.ts.map +1 -1
  35. package/dist/types/src/browser/react/item.d.ts.map +1 -1
  36. package/dist/types/src/client.d.ts +1 -1
  37. package/dist/types/src/client.d.ts.map +1 -1
  38. package/dist/types/src/db/write/createMetadata.d.ts.map +1 -1
  39. package/dist/types/src/db/write/createNewItem.d.ts.map +1 -1
  40. package/dist/types/src/db/write/updateMetadata.d.ts +2 -1
  41. package/dist/types/src/db/write/updateMetadata.d.ts.map +1 -1
  42. package/dist/types/src/interfaces/IItem.d.ts +3 -0
  43. package/dist/types/src/interfaces/IItem.d.ts.map +1 -1
  44. package/package.json +1 -1
  45. package/dist/Db-BhLWMUOe.js.map +0 -1
  46. package/dist/index-C93o7-zP.js.map +0 -1
@@ -1,4 +1,4 @@
1
- export { I as Item } from './index-B6FQruEq.js';
1
+ export { I as Item } from './index-CKrLHw3B.js';
2
2
  import 'immer';
3
3
  import 'reflect-metadata';
4
4
  import '@sinclair/typebox';
@@ -22,4 +22,4 @@ import 'drizzle-orm/casing';
22
22
  import 'react';
23
23
  import 'use-immer';
24
24
  import '@xstate/react';
25
- //# sourceMappingURL=index-C93o7-zP.js.map
25
+ //# sourceMappingURL=index-Dv8GeuSw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-Dv8GeuSw.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/main.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'immer';
2
2
  import 'reflect-metadata';
3
- export { D as Db, c as ImageSrc, d as Item, e as ItemProperty, J as Json, L as List, M as Model, P as Property, R as Relation, T as Text, s as client, r as eventEmitter, p as getCorrectId, q as getGlobalService, h as useCreateItem, j as useDeleteItem, k as useGlobalServiceStatus, f as useItem, g as useItemProperties, i as useItemProperty, u as useItems, m as usePersistedSnapshots, l as usePublishItem, o as useService, n as useServices, w as withSeed } from './index-B6FQruEq.js';
3
+ export { D as Db, c as ImageSrc, d as Item, e as ItemProperty, J as Json, L as List, M as Model, P as Property, R as Relation, T as Text, s as client, r as eventEmitter, p as getCorrectId, q as getGlobalService, h as useCreateItem, j as useDeleteItem, k as useGlobalServiceStatus, f as useItem, g as useItemProperties, i as useItemProperty, u as useItems, m as usePersistedSnapshots, l as usePublishItem, o as useService, n as useServices, w as withSeed } from './index-CKrLHw3B.js';
4
4
  export { B as BaseArweaveClient, a as BaseEasClient, c as BaseFileManager, b as BaseQueryClient } from './constants-C03RQQht.js';
5
5
  import '@sinclair/typebox';
6
6
  import 'xstate';
@@ -1,6 +1,6 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import 'reflect-metadata';
3
- import { T as Text, M as Model } from './index-B6FQruEq.js';
3
+ import { T as Text, M as Model } from './index-CKrLHw3B.js';
4
4
  import 'immer';
5
5
  import '@sinclair/typebox';
6
6
  import 'xstate';
@@ -70,4 +70,4 @@ const models = {
70
70
  };
71
71
 
72
72
  export { models };
73
- //# sourceMappingURL=seed.schema.config-ClOsMOKS.js.map
73
+ //# sourceMappingURL=seed.schema.config-1s-iWHq_.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"seed.schema.config-ClOsMOKS.js","sources":["../../src/db/configs/seed.schema.config.ts"],"sourcesContent":["import { Model, Text } from '@/schema'\n\n@Model\nclass Seed {\n @Text() uid!: string\n @Text() type!: string\n}\n\n@Model\nclass Version {\n @Text() seedUid!: string\n @Text() note!: string\n}\n\n@Model\nclass Metadata {\n @Text() key!: string\n @Text() value!: string\n}\n\nexport const models = {\n Seed,\n Version,\n Metadata,\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,IAAM,IAAI,GAAV,MAAM,IAAI,CAAA;CAGT;AAFS,UAAA,CAAA;AAAP,IAAA,IAAI,EAAE;;AAAa,CAAA,EAAA,IAAA,CAAA,SAAA,EAAA,KAAA,EAAA,SAAA,CAAA;AACZ,UAAA,CAAA;AAAP,IAAA,IAAI,EAAE;;AAAc,CAAA,EAAA,IAAA,CAAA,SAAA,EAAA,MAAA,EAAA,SAAA,CAAA;AAFjB,IAAI,GAAA,UAAA,CAAA;IADT;AACK,CAAA,EAAA,IAAI,CAGT;AAGD,IAAM,OAAO,GAAb,MAAM,OAAO,CAAA;CAGZ;AAFS,UAAA,CAAA;AAAP,IAAA,IAAI,EAAE;;AAAiB,CAAA,EAAA,OAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA;AAChB,UAAA,CAAA;AAAP,IAAA,IAAI,EAAE;;AAAc,CAAA,EAAA,OAAA,CAAA,SAAA,EAAA,MAAA,EAAA,SAAA,CAAA;AAFjB,OAAO,GAAA,UAAA,CAAA;IADZ;AACK,CAAA,EAAA,OAAO,CAGZ;AAGD,IAAM,QAAQ,GAAd,MAAM,QAAQ,CAAA;CAGb;AAFS,UAAA,CAAA;AAAP,IAAA,IAAI,EAAE;;AAAa,CAAA,EAAA,QAAA,CAAA,SAAA,EAAA,KAAA,EAAA,SAAA,CAAA;AACZ,UAAA,CAAA;AAAP,IAAA,IAAI,EAAE;;AAAe,CAAA,EAAA,QAAA,CAAA,SAAA,EAAA,OAAA,EAAA,SAAA,CAAA;AAFlB,QAAQ,GAAA,UAAA,CAAA;IADb;AACK,CAAA,EAAA,QAAQ,CAGb;AAEY,MAAA,MAAM,GAAG;IACpB,IAAI;IACJ,OAAO;IACP,QAAQ;;;;;"}
1
+ {"version":3,"file":"seed.schema.config-1s-iWHq_.js","sources":["../../src/db/configs/seed.schema.config.ts"],"sourcesContent":["import { Model, Text } from '@/schema'\n\n@Model\nclass Seed {\n @Text() uid!: string\n @Text() type!: string\n}\n\n@Model\nclass Version {\n @Text() seedUid!: string\n @Text() note!: string\n}\n\n@Model\nclass Metadata {\n @Text() key!: string\n @Text() value!: string\n}\n\nexport const models = {\n Seed,\n Version,\n Metadata,\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,IAAM,IAAI,GAAV,MAAM,IAAI,CAAA;CAGT;AAFS,UAAA,CAAA;AAAP,IAAA,IAAI,EAAE;;AAAa,CAAA,EAAA,IAAA,CAAA,SAAA,EAAA,KAAA,EAAA,SAAA,CAAA;AACZ,UAAA,CAAA;AAAP,IAAA,IAAI,EAAE;;AAAc,CAAA,EAAA,IAAA,CAAA,SAAA,EAAA,MAAA,EAAA,SAAA,CAAA;AAFjB,IAAI,GAAA,UAAA,CAAA;IADT;AACK,CAAA,EAAA,IAAI,CAGT;AAGD,IAAM,OAAO,GAAb,MAAM,OAAO,CAAA;CAGZ;AAFS,UAAA,CAAA;AAAP,IAAA,IAAI,EAAE;;AAAiB,CAAA,EAAA,OAAA,CAAA,SAAA,EAAA,SAAA,EAAA,SAAA,CAAA;AAChB,UAAA,CAAA;AAAP,IAAA,IAAI,EAAE;;AAAc,CAAA,EAAA,OAAA,CAAA,SAAA,EAAA,MAAA,EAAA,SAAA,CAAA;AAFjB,OAAO,GAAA,UAAA,CAAA;IADZ;AACK,CAAA,EAAA,OAAO,CAGZ;AAGD,IAAM,QAAQ,GAAd,MAAM,QAAQ,CAAA;CAGb;AAFS,UAAA,CAAA;AAAP,IAAA,IAAI,EAAE;;AAAa,CAAA,EAAA,QAAA,CAAA,SAAA,EAAA,KAAA,EAAA,SAAA,CAAA;AACZ,UAAA,CAAA;AAAP,IAAA,IAAI,EAAE;;AAAe,CAAA,EAAA,QAAA,CAAA,SAAA,EAAA,OAAA,EAAA,SAAA,CAAA;AAFlB,QAAQ,GAAA,UAAA,CAAA;IADb;AACK,CAAA,EAAA,QAAQ,CAGb;AAEY,MAAA,MAAM,GAAG;IACpB,IAAI;IACJ,OAAO;IACP,QAAQ;;;;;"}
@@ -226,8 +226,9 @@ export abstract class BaseItem<T extends ModelValues<ModelSchema>> implements II
226
226
  if (!props.modelName) {
227
227
  throw new Error('Model name is required to create an item')
228
228
  }
229
- const { seedLocalId, versionLocalId, versionUid } = await createNewItem({
229
+ const { seedLocalId, versionLocalId, } = await createNewItem({
230
230
  modelName: props.modelName,
231
+ ...props,
231
232
  })
232
233
  props.seedLocalId = seedLocalId
233
234
  props.latestVersionLocalId = versionLocalId
@@ -267,9 +268,9 @@ export abstract class BaseItem<T extends ModelValues<ModelSchema>> implements II
267
268
  static async all(
268
269
  modelName?: string,
269
270
  deleted?: boolean,
270
- ): Promise<IItem<any>[]> {
271
+ ): Promise<BaseItem<any>[]> {
271
272
  const itemsData = await getItemsData({ modelName, deleted })
272
- const itemInstances: IItem<any>[] = []
273
+ const itemInstances: BaseItem<any>[] = []
273
274
  for (const itemData of itemsData) {
274
275
  itemInstances.push(
275
276
  await BaseItem.create({
@@ -381,6 +382,10 @@ export abstract class BaseItem<T extends ModelValues<ModelSchema>> implements II
381
382
  return this.serviceContext.latestVersionUid as VersionsType
382
383
  }
383
384
 
385
+ get latestVersionLocalId(): string {
386
+ return this.serviceContext.latestVersionLocalId as string
387
+ }
388
+
384
389
  get modelName(): string {
385
390
  return this.serviceContext.modelName as string
386
391
  }
@@ -393,6 +398,14 @@ export abstract class BaseItem<T extends ModelValues<ModelSchema>> implements II
393
398
  return this.serviceContext.attestationCreatedAt as number
394
399
  }
395
400
 
401
+ get versionsCount(): number {
402
+ return this.serviceContext.versionsCount as number
403
+ }
404
+
405
+ get lastVersionPublishedAt(): number {
406
+ return this.serviceContext.lastVersionPublishedAt as number
407
+ }
408
+
396
409
  unload(): void {
397
410
  this._subscription?.unsubscribe()
398
411
  this._service.stop()
@@ -202,8 +202,8 @@ export abstract class BaseItemProperty<PropertyType> implements IItemProperty<Pr
202
202
 
203
203
  this._subject.next(renderValue)
204
204
  // TODO: Maybe have this only update the property?
205
- // if (context.seedLocalId) {
206
- // eventEmitter.emit(`item.${modelName}.${context.seedLocalId}.update`)
205
+ // if (context.seedLocalId || context.seedUid) {
206
+ // eventEmitter.emit(`property.${context.seedUid || context.seedLocalId}.${propertyName}.update`)
207
207
  // }
208
208
  // if (context.seedUid) {
209
209
  // eventEmitter.emit(`item.${modelName}.${context.seedUid}.update`)
package/dist/src/IItem.ts CHANGED
@@ -17,7 +17,10 @@ export interface IItem<T extends ModelValues<ModelSchema>> {
17
17
  readonly seedUid?: string
18
18
  readonly schemaUid: string
19
19
  readonly latestVersionUid: VersionsType
20
+ readonly latestVersionLocalId: string
20
21
  readonly modelName: string
21
22
  readonly properties: Record<string, IItemProperty<any>>
22
23
  readonly attestationCreatedAt: number
23
- }
24
+ readonly versionsCount: number
25
+ readonly lastVersionPublishedAt: number
26
+ }
@@ -1,56 +1,294 @@
1
1
  import { EventObject, fromCallback } from 'xstate'
2
- import { downloadMachine } from '@/schema/file/download'
2
+ import { fetchAllFilesMachine } from '@/schema/file/fetchAll/index'
3
+ import { ARWEAVE_HOST } from '@/services/internal/constants'
3
4
  import { GET_FILES_METADATA } from '@/schema/file/queries'
5
+ import { getArweave } from '@/helpers/ArweaveClient'
6
+ import fs from '@zenfs/core'
7
+ import {
8
+ getDataTypeFromString,
9
+ getMimeType,
10
+ identifyString,
11
+ } from '@/helpers'
12
+ import { appState } from '@/seedSchema'
13
+ import { eq } from 'drizzle-orm'
4
14
  import { BaseEasClient } from '@/helpers/EasClient/BaseEasClient'
5
15
  import { BaseQueryClient } from '@/helpers/QueryClient/BaseQueryClient'
16
+ import debug from 'debug'
17
+ import { BaseDb } from '@/db/Db/BaseDb'
18
+ import { saveAppState } from '@/db/write/saveAppState'
6
19
 
20
+ const logger = debug('app:file:actors:fetchAll')
7
21
 
8
- export const fetchMetadata = fromCallback<EventObject, typeof downloadMachine>(
9
- ({ sendBack, input: { context } }) => {
10
- const { addresses } = context
22
+ type FileType = {
23
+ mimeType: string
24
+ extension: string
25
+ }
11
26
 
12
- const fetchMetadata = async () => {
13
- const queryClient = BaseQueryClient.getQueryClient()
14
- const easClient = BaseEasClient.getEasClient()
27
+ // Map of common MIME types to file extensions
28
+ const fileTypeMap: Record<string, FileType> = {
29
+ 'image/jpeg': { mimeType: 'image/jpeg', extension: '.jpg' },
30
+ 'image/png': { mimeType: 'image/png', extension: '.png' },
31
+ 'application/json': { mimeType: 'application/json', extension: '.json' },
32
+ 'text/plain': { mimeType: 'text/plain', extension: '.txt' },
33
+ // Add more MIME types and file extensions as needed
34
+ }
15
35
 
16
- const metadataRecords = await queryClient.fetchQuery({
17
- queryKey: ['getFilesMetadata', ...addresses],
18
- queryFn: async () =>
19
- easClient.request(GET_FILES_METADATA, {
20
- where: {
21
- attester: {
22
- in: addresses,
23
- },
24
- decodedDataJson: {
25
- contains: 'transactionId',
36
+ export const fetchAllMetadataRecords = fromCallback<
37
+ EventObject,
38
+ typeof fetchAllFilesMachine
39
+ >(({ sendBack, receive, input: { context, event } }) => {
40
+ const { addresses } = context
41
+
42
+ const _fetchAllMetadataRecords = async () => {
43
+ const queryClient = BaseQueryClient.getQueryClient()
44
+ const easClient = BaseEasClient.getEasClient()
45
+
46
+ const { filesMetadata } = await queryClient.fetchQuery({
47
+ queryKey: ['getFilesMetadata', ...addresses],
48
+ queryFn: async () =>
49
+ easClient.request(GET_FILES_METADATA, {
50
+ where: {
51
+ attester: {
52
+ in: addresses,
53
+ },
54
+ schema: {
55
+ is: {
56
+ id: {
57
+ equals:
58
+ '0x55fdefb36fcbbaebeb7d6b41dc3a1a9666e4e42154267c889de064faa7ede517',
59
+ },
26
60
  },
27
61
  },
28
- }),
29
- })
62
+ },
63
+ }),
64
+ })
30
65
 
31
- return metadataRecords
32
- }
66
+ return filesMetadata
67
+ }
33
68
 
34
- fetchMetadata().then((metadataRecords) => {
35
- sendBack({ type: 'fetchingMetadataSuccess', metadataRecords })
36
- })
69
+ _fetchAllMetadataRecords().then((filesMetadata) => {
70
+ sendBack({ type: 'fetchingAllMetadataRecordsSuccess', filesMetadata })
71
+ })
37
72
 
38
- return () => { }
39
- },
40
- )
73
+ return () => { }
74
+ })
41
75
 
42
- export const fetchBinaryData = fromCallback<
76
+ export const fetchAllBinaryData = fromCallback<
43
77
  EventObject,
44
- typeof downloadMachine
45
- >(({ sendBack, receive, input: { context } }) => {
46
- const { addresses } = context
78
+ typeof fetchAllFilesMachine
79
+ >(({ sendBack, input: { context } }) => {
80
+ const { filesMetadata, addresses } = context
81
+
82
+ const _fetchAllBinaryData = async () => {
83
+ if (!(await fs.promises.exists('/files'))) {
84
+ await fs.promises.mkdir('/files', { recursive: true })
85
+ }
86
+
87
+ if (!(await fs.promises.exists('/files/html'))) {
88
+ await fs.promises.mkdir('/files/html', { recursive: true })
89
+ }
90
+
91
+ if (!(await fs.promises.exists('/files/json'))) {
92
+ await fs.promises.mkdir('/files/json', { recursive: true })
93
+ }
94
+
95
+ if (!(await fs.promises.exists('/files/images'))) {
96
+ await fs.promises.mkdir('/files/images', { recursive: true })
97
+ }
98
+
99
+ const appDb = BaseDb.getAppDb()
100
+
101
+ if (!appDb) {
102
+ logger('[fetchAll/actors] [fetchAllBinaryData] seedDb not available')
103
+ return []
104
+ }
105
+
106
+ for (const fileMetadata of filesMetadata) {
107
+ const json = JSON.parse(fileMetadata.decodedDataJson)
108
+ const transactionId = json[0].value.value
109
+
110
+ const excludedTransactionsQuery = await appDb
111
+ .select()
112
+ .from(appState)
113
+ .where(eq(appState.key, 'excludedTransactions'))
114
+
115
+ let excludedTransactions = new Set<string>()
116
+
117
+ if (excludedTransactionsQuery && excludedTransactionsQuery.length === 1) {
118
+ const valueString = excludedTransactionsQuery[0].value
119
+ if (valueString) {
120
+ const excludedTransactionsArray = JSON.parse(valueString)
121
+ excludedTransactions = new Set(excludedTransactionsArray)
122
+ }
123
+ }
124
+
125
+ if (excludedTransactions.has(transactionId)) {
126
+ continue
127
+ }
128
+
129
+ const arweave = getArweave()
130
+
131
+ if (!arweave) {
132
+ logger('[fetchAll/actors] [fetchAllBinaryData] arweave not available')
133
+ return []
134
+ }
135
+
136
+ try {
137
+ const res = await fetch(
138
+ `https://${ARWEAVE_HOST}/tx/${transactionId}/status`,
139
+ )
140
+
141
+ if (res.status !== 200) {
142
+ logger(
143
+ `[fetchAll/actors] [fetchAllBinaryData] error fetching transaction data for ${transactionId}`,
144
+ )
145
+
146
+ excludedTransactions.add(transactionId)
147
+
148
+ await saveAppState(
149
+ 'excludedTransactions',
150
+ JSON.stringify(Array.from(excludedTransactions)),
151
+ )
152
+
153
+ logger(
154
+ '[fetchAll/actors] [fetchAllBinaryData] updated excludedTransactions:',
155
+ excludedTransactions,
156
+ )
157
+
158
+ continue
159
+ }
160
+
161
+ const dataString = await arweave.transactions
162
+ .getData(transactionId, {
163
+ decode: true,
164
+ string: true,
165
+ })
166
+ .catch((error) => {
167
+ logger(
168
+ `[fetchAll/actors] [fetchAllBinaryData] error fetching transaction data for ${transactionId}`,
169
+ error,
170
+ )
171
+ })
172
+
173
+ const dataUint8Array = await arweave.transactions.getData(transactionId)
174
+ // let buffer
175
+ //
176
+ // if (dataUint8Array && dataUint8Array instanceof Uint8Array) {
177
+ // }
178
+
179
+ let contentType = identifyString(dataString)
180
+ if (
181
+ contentType !== 'json' &&
182
+ contentType !== 'base64' &&
183
+ contentType !== 'html'
184
+ ) {
185
+ const possibleImageType = getDataTypeFromString(dataString)
186
+ if (!possibleImageType) {
187
+ logger(
188
+ `[fetchAll/actors] [fetchAllBinaryData] transaction ${transactionId} data not in expected format: ${possibleImageType}`,
189
+ )
190
+ continue
191
+ }
192
+
193
+ contentType = possibleImageType
194
+ }
195
+
196
+ if (contentType === 'url') {
197
+ const url = dataString as string
198
+ const response = await fetch(url)
199
+ if (!response.ok) {
200
+ throw new Error(`Failed to fetch image: ${response.statusText}`)
201
+ }
202
+
203
+ // Get the image as a Blob
204
+ const blob = await response.blob()
205
+ const buffer = await blob.arrayBuffer()
206
+ const bufferUint8Array = new Uint8Array(buffer)
207
+
208
+ // Extract the file extension from the URL
209
+ const extensionMatch = url.match(
210
+ /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i,
211
+ )
212
+ if (!extensionMatch) {
213
+ throw new Error(
214
+ 'Unable to determine the file extension from the URL.',
215
+ )
216
+ }
217
+ const fileExtension = extensionMatch[0] // e.g., ".jpg"
218
+
219
+ // Set the file name (you can customize this)
220
+ // const fileNameFromUrl = `${transactionId}${fileExtension}`
221
+
222
+ await fs.promises.writeFile(
223
+ `/files/images/${transactionId}`,
224
+ bufferUint8Array,
225
+ {
226
+ encoding: 'binary',
227
+ },
228
+ )
229
+
230
+ continue
231
+ }
232
+
233
+ let mimeType = getMimeType(dataString as string)
234
+ let fileExtension = mimeType
235
+
236
+ if (fileExtension && fileExtension?.startsWith('image')) {
237
+ fileExtension = fileExtension.replace('image/', '')
238
+ }
239
+
240
+ let fileName = transactionId
241
+
242
+ if (contentType === 'base64') {
243
+ if (mimeType) {
244
+ fileName += `.${fileExtension}`
245
+ }
246
+
247
+ // Remove the Base64 header if it exists (e.g., "data:image/png;base64,")
248
+ const base64Data = dataString.split(',').pop() || ''
249
+
250
+ // Decode the Base64 string to binary
251
+ const binaryString = atob(base64Data)
252
+ const length = binaryString.length
253
+ const binaryData = new Uint8Array(length)
254
+
255
+ for (let i = 0; i < length; i++) {
256
+ binaryData[i] = binaryString.charCodeAt(i)
257
+ }
258
+
259
+ console.log(`attempting to writeFile to /files/images/${fileName}`)
260
+
261
+ await fs.promises.writeFile(`/files/images/${fileName}`, binaryData, {
262
+ encoding: 'binary',
263
+ })
264
+
265
+ // if (dataUint8Array && dataUint8Array instanceof Uint8Array) {
266
+ // await fs.promises.writeFile(
267
+ // `/files/images/${fileName}`,
268
+ // dataUint8Array,
269
+ // )
270
+ // }
271
+ }
272
+
273
+ if (contentType === 'html') {
274
+ fileName += '.html'
275
+ await fs.promises.writeFile(`/files/html/${fileName}`, dataString)
276
+ }
277
+
278
+ if (contentType === 'json') {
279
+ fileName += '.json'
280
+ await fs.promises.writeFile(`/files/json/${fileName}`, dataString)
281
+ }
282
+ } catch (error) {
283
+ logger(error)
284
+ }
285
+ }
47
286
 
48
- const fetchBinaryData = async () => {
49
287
  return []
50
288
  }
51
289
 
52
- fetchBinaryData().then(() => {
53
- sendBack({ type: 'fetchingBinaryDataSuccess' })
290
+ _fetchAllBinaryData().then((binaryData) => {
291
+ sendBack({ type: 'fetchingAllBinaryDataSuccess', binaryData })
54
292
  })
55
293
 
56
294
  return () => { }
@@ -20,7 +20,6 @@ import { initFileManager } from './helpers/FileManager'
20
20
  import { initDb } from './db/Db'
21
21
  import debug from 'debug'
22
22
  import { appState } from './seedSchema'
23
- import { BaseDb } from './db/Db/BaseDb'
24
23
 
25
24
  const logger = debug('app:client')
26
25
 
@@ -78,7 +77,14 @@ const client = {
78
77
  setModel(key, value)
79
78
  }
80
79
  },
81
- setAddresses: (addresses: string[]) => {
80
+ setAddresses: async(addresses: string[]) => {
81
+ const {BaseDb} = await import('./db/Db/BaseDb')
82
+ if (!BaseDb) {
83
+ throw new Error('BaseDb not found')
84
+ }
85
+ if (!BaseDb.PlatformClass) {
86
+ await initDb()
87
+ }
82
88
  const appDb = BaseDb.getAppDb()
83
89
  if (!appDb) {
84
90
  throw new Error('App DB not found')
@@ -6,6 +6,8 @@ import { GET_SCHEMA_BY_NAME, } from '@/Item/queries'
6
6
  import { INTERNAL_DATA_TYPES } from '@/helpers/constants'
7
7
  import { toSnakeCase } from 'drizzle-orm/casing'
8
8
  import { Schema } from '@/graphql/gql/graphql'
9
+ import path from 'path'
10
+ import fs from '@zenfs/core'
9
11
 
10
12
  type CreateMetadata = (
11
13
  metadataValues: Partial<MetadataType>,
@@ -21,19 +23,22 @@ export const createMetadata: CreateMetadata = async (
21
23
  metadataValues.localId = generateId()
22
24
 
23
25
  if (!metadataValues.modelType && metadataValues.modelName) {
24
- metadataValues.modelType = metadataValues.modelName.toLowerCase()
26
+ metadataValues.modelType = toSnakeCase(metadataValues.modelName)
25
27
  }
26
28
 
27
29
  const isItemStorage = propertyRecordSchema && propertyRecordSchema.storageType === 'ItemStorage'
28
30
 
29
- if (
30
- propertyRecordSchema &&
31
- propertyRecordSchema.localStorageDir &&
32
- isItemStorage
33
- ) {
34
- metadataValues.refResolvedValue = `${metadataValues.seedUid || metadataValues.seedLocalId}${propertyRecordSchema.filenameSuffix}`
35
- metadataValues.refValueType = 'file'
36
- }
31
+ // if (
32
+ // propertyRecordSchema &&
33
+ // propertyRecordSchema.localStorageDir &&
34
+ // isItemStorage
35
+ // ) {
36
+ // const filename = `${metadataValues.seedUid || metadataValues.seedLocalId}${propertyRecordSchema.filenameSuffix}`
37
+ // const filePath = path.join(propertyRecordSchema.localStorageDir, filename)
38
+ // await fs.promises.writeFile(filePath, metadataValues.propertyValue)
39
+ // metadataValues.propertyValue = filename
40
+ // metadataValues.refValueType = 'file'
41
+ // }
37
42
 
38
43
  if (!isItemStorage && !metadataValues.schemaUid && propertyRecordSchema) {
39
44
  const queryClient = BaseQueryClient.getQueryClient()
@@ -3,6 +3,8 @@ import { getModel } from '@/stores/modelClass'
3
3
  import { createSeed } from './createSeed'
4
4
  import { createVersion } from './createVersion'
5
5
  import { createMetadata } from './createMetadata'
6
+ import { toSnakeCase } from 'drizzle-orm/casing'
7
+ import { eventEmitter } from '@/eventBus'
6
8
 
7
9
  type CreateNewItemProps = Partial<ModelValues<any>> & {
8
10
  modelName: string
@@ -22,11 +24,11 @@ export const createNewItem = async ({
22
24
  throw new Error('A model name is required for createNewItem')
23
25
  }
24
26
 
25
- const seedType = modelName.toLowerCase()
27
+ const seedType = toSnakeCase(modelName)
26
28
 
27
29
  const newSeedId = await createSeed({ type: seedType })
28
30
 
29
- const newVersionId = await createVersion({ seedLocalId: newSeedId })
31
+ const newVersionId = await createVersion({ seedLocalId: newSeedId, seedType: toSnakeCase(modelName) })
30
32
 
31
33
  const propertySchemas = getModel(modelName)?.schema
32
34
 
@@ -49,6 +51,8 @@ export const createNewItem = async ({
49
51
  )
50
52
  }
51
53
 
54
+ eventEmitter.emit('item.requestAll', { modelName })
55
+
52
56
  return {
53
57
  modelName,
54
58
  seedLocalId: newSeedId,
@@ -175,10 +175,6 @@ export const saveImageSrc = fromCallback<
175
175
 
176
176
  const refResolvedDisplayValue = await BaseFileManager.getContentUrlFromPath(filePath)
177
177
 
178
- if (!schemaUid) {
179
- schemaUid = getSchemaUidForSchemaDefinition(propertyName)
180
- }
181
-
182
178
  let newLocalId
183
179
 
184
180
  if (!localId) {
@@ -78,10 +78,16 @@ export const saveItemStorage = fromCallback<
78
78
  propertyData = queryRows[0]
79
79
  }
80
80
 
81
- if (!propertyData) {
81
+ if (!propertyData && newValue) {
82
+
83
+ const filename = `${seedUid || seedLocalId}${propertyRecordSchema.filenameSuffix}`
84
+ const writeToPath = `/files/${propertyRecordSchema.localStorageDir}/${filename}`
85
+ await fs.promises.writeFile(writeToPath, newValue as string)
86
+
82
87
  const propertyDataRows = await createMetadata(
83
88
  {
84
89
  propertyName,
90
+ propertyValue: filename,
85
91
  modelType: modelName.toLowerCase(),
86
92
  seedLocalId,
87
93
  seedUid,
@@ -1,12 +1,20 @@
1
1
  import { metadata, MetadataType } from '@/seedSchema'
2
2
  import { BaseDb } from '@/db/Db/BaseDb'
3
3
  import { eq } from 'drizzle-orm'
4
+ import { PropertyType } from '@/types'
5
+ import { BaseQueryClient } from '@/helpers/QueryClient/BaseQueryClient'
6
+ import { BaseEasClient } from '@/helpers/EasClient/BaseEasClient'
7
+ import { INTERNAL_DATA_TYPES } from '@/helpers/constants'
8
+ import { toSnakeCase } from 'drizzle-orm/casing'
9
+ import { Schema } from '@/graphql/gql/graphql'
10
+ import { GET_SCHEMA_BY_NAME } from '@/Item/queries'
4
11
 
5
12
  type UpdateMetadata = (
6
13
  metadataValues: Partial<MetadataType>,
14
+ propertyRecordSchema?: PropertyType | undefined,
7
15
  ) => Promise<MetadataType>
8
16
 
9
- export const updateMetadata: UpdateMetadata = async (metadataValues) => {
17
+ export const updateMetadata: UpdateMetadata = async (metadataValues, propertyRecordSchema) => {
10
18
  const appDb = BaseDb.getAppDb()
11
19
 
12
20
  const { localId, ...rest } = metadataValues
@@ -14,6 +22,38 @@ export const updateMetadata: UpdateMetadata = async (metadataValues) => {
14
22
  if (!localId) {
15
23
  throw new Error('No localId provided to updateMetadata')
16
24
  }
25
+
26
+ const isItemStorage = propertyRecordSchema && propertyRecordSchema.storageType === 'ItemStorage'
27
+
28
+ if (
29
+ !isItemStorage &&
30
+ propertyRecordSchema &&
31
+ (!metadataValues.schemaUid || metadataValues.schemaUid === 'undefined' )
32
+ ) {
33
+ const queryClient = BaseQueryClient.getQueryClient()
34
+ const easClient = BaseEasClient.getEasClient()
35
+
36
+ const easDataType = INTERNAL_DATA_TYPES[propertyRecordSchema.dataType].eas
37
+
38
+ const propertyNameSnakeCase = toSnakeCase(metadataValues.propertyName)
39
+
40
+ const queryResult = await queryClient.fetchQuery({
41
+ queryKey: [`getSchemaByName${metadataValues.propertyName}`],
42
+ queryFn: async (): Promise<{schemas: Schema[]}> =>
43
+ easClient.request(GET_SCHEMA_BY_NAME, {
44
+ where: {
45
+ schema: {
46
+ equals: `${easDataType} ${propertyNameSnakeCase}`,
47
+ },
48
+ },
49
+ }),
50
+ })
51
+
52
+ if (queryResult && queryResult.schemas.length > 0) {
53
+ metadataValues.schemaUid = queryResult.schemas[0].id
54
+ }
55
+
56
+ }
17
57
 
18
58
  await appDb.update(metadata).set(rest).where(eq(metadata.localId, localId))
19
59
  }