@seedprotocol/sdk 0.1.47 → 0.1.49

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 (141) hide show
  1. package/dist/bin.js.map +1 -1
  2. package/dist/constants-BLctWkrn.js.map +1 -1
  3. package/dist/{index-DWf9Ls94.js → index-DMIKRod-.js} +3995 -3995
  4. package/dist/index-DMIKRod-.js.map +1 -0
  5. package/dist/{index-B2WbNudj.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-mBqth17w.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 +280 -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 +73 -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/item/single/actors/hydrateExistingItem.d.ts +3 -1
  126. package/dist/types/src/browser/item/single/actors/hydrateExistingItem.d.ts.map +1 -1
  127. package/dist/types/src/browser/item/single/actors/saveDataToDb.d.ts +3 -3
  128. package/dist/types/src/browser/item/single/itemMachineSingle.d.ts +3 -3
  129. package/dist/types/src/browser/property/ItemProperty.d.ts +7 -7
  130. package/dist/types/src/browser/property/ItemProperty.d.ts.map +1 -1
  131. package/dist/types/src/browser/property/actors/resolveRemoteStorage.d.ts +3 -3
  132. package/dist/types/src/browser/react/trash.d.ts +1 -1
  133. package/dist/types/src/browser/react/trash.d.ts.map +1 -1
  134. package/dist/types/src/browser/services/db/dbMachine.d.ts +6 -6
  135. package/dist/types/src/browser/services/publish/publishMachine.d.ts +17 -17
  136. package/dist/types/src/types/machines.d.ts +4 -0
  137. package/dist/types/src/types/machines.d.ts.map +1 -1
  138. package/package.json +2 -2
  139. package/dist/index-B2WbNudj.js.map +0 -1
  140. package/dist/index-DWf9Ls94.js.map +0 -1
  141. package/dist/seed.schema.config-mBqth17w.js.map +0 -1
@@ -0,0 +1,324 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react'
2
+ import { createNewItem } from '@/browser/db/write'
3
+ import { Item } from '@/browser/item'
4
+ import { eventEmitter } from '@/eventBus'
5
+ import { useImmer } from 'use-immer'
6
+ import { orderBy } from 'lodash-es'
7
+ import { getAreItemEventHandlersReady } from '@/browser/events'
8
+ import { Subscription } from 'xstate'
9
+ import { useSelector } from '@xstate/react'
10
+ import debug from 'debug'
11
+ import { useGlobalServiceStatus, useIsDbReady } from '@/browser/react/services'
12
+ import { ModelValues } from '@/types'
13
+
14
+ const logger = debug('app:react:item')
15
+
16
+ type UseItemProps = {
17
+ modelName: string
18
+ seedLocalId?: string
19
+ seedUid?: string
20
+ }
21
+
22
+ type UseItemReturn<T extends ModelValues<T>> = {
23
+ item: Item<T> | undefined
24
+ itemData: ItemData<T>
25
+ itemStatus: string | Record<string, unknown> | undefined
26
+ }
27
+
28
+ type UseItem<T> = (props: UseItemProps) => UseItemReturn<T>
29
+
30
+ type ItemData<T> = Record<string, Partial<T>>
31
+
32
+ export const useItem: UseItem<any> = ({ modelName, seedLocalId, seedUid }) => {
33
+ const [itemData, setItemData] = useImmer<ItemData<any>>({})
34
+ const [item, setItem] = useState<Item<any> | undefined>()
35
+ const [itemSubscription, setItemSubscription] = useState<
36
+ Subscription | undefined
37
+ >()
38
+
39
+ const { status, internalStatus } = useGlobalServiceStatus()
40
+
41
+ const isReadingDb = useRef(false)
42
+
43
+ const itemStatus = useSelector(
44
+ item?.getService(),
45
+ (snapshot) => snapshot?.value,
46
+ )
47
+
48
+ const updateItem = useCallback((newItem: Item<any>) => {
49
+ setItemData((draft) => {
50
+ Object.keys(newItem.properties).forEach((propertyName) => {
51
+ const value = newItem[propertyName]
52
+ draft[propertyName] = value
53
+ })
54
+ })
55
+ }, [])
56
+
57
+ const readFromDb = useCallback(async () => {
58
+ if (
59
+ isReadingDb.current ||
60
+ internalStatus !== 'ready' ||
61
+ (!seedUid && !seedLocalId)
62
+ ) {
63
+ return
64
+ }
65
+ isReadingDb.current = true
66
+ const foundItem = await Item.find({
67
+ modelName,
68
+ seedLocalId,
69
+ seedUid,
70
+ })
71
+ if (!foundItem) {
72
+ logger('[useItem] [getItemFromDb] no item found', modelName, seedLocalId)
73
+ return
74
+ }
75
+ setItem(foundItem)
76
+ updateItem(foundItem)
77
+ isReadingDb.current = false
78
+ }, [internalStatus])
79
+
80
+ const listenerRef = useRef(readFromDb)
81
+
82
+ useEffect(() => {
83
+ listenerRef.current = readFromDb
84
+ }, [readFromDb])
85
+
86
+ useEffect(() => {
87
+ if (internalStatus === 'ready') {
88
+ listenerRef.current()
89
+ }
90
+ }, [internalStatus, status])
91
+
92
+ useEffect(() => {
93
+ if (item && !itemSubscription) {
94
+ const subscription = item.subscribe(async (_) => {
95
+ const newItem = await Item.find({ modelName, seedLocalId, seedUid })
96
+ if (!newItem) {
97
+ logger(
98
+ '[useItem] [itemSubscription] no item found',
99
+ modelName,
100
+ seedLocalId,
101
+ )
102
+ return
103
+ }
104
+ updateItem(newItem)
105
+ setItem(newItem)
106
+ })
107
+ setItemSubscription(subscription)
108
+ }
109
+
110
+ return () => {
111
+ itemSubscription?.unsubscribe()
112
+ }
113
+ }, [item, itemSubscription])
114
+
115
+ useEffect(() => {
116
+ const seedId = seedUid || seedLocalId
117
+
118
+ eventEmitter.addListener(`item.${modelName}.${seedId}.update`, () => {
119
+ listenerRef.current()
120
+ })
121
+
122
+ return () => {
123
+ eventEmitter.removeListener(
124
+ `item.${modelName}.${seedId}.update`,
125
+ readFromDb,
126
+ )
127
+ }
128
+ }, [])
129
+
130
+ return {
131
+ item,
132
+ itemData,
133
+ itemStatus,
134
+ }
135
+ }
136
+ type UseItemsReturn = {
137
+ items: Item<any>[]
138
+ isReadingDb: boolean
139
+ isInitialized: boolean
140
+ }
141
+ type UseItemsProps = {
142
+ modelName?: string
143
+ deleted?: boolean
144
+ }
145
+ type UseItems = (props: UseItemsProps) => UseItemsReturn
146
+ export const useItems: UseItems = ({ modelName, deleted }) => {
147
+ const [items, setItems] = useImmer<Item<any>[]>([])
148
+ const [isReadingDb, setIsReadingDb] = useState(false)
149
+ const [isInitialized, setIsInitialized] = useState(false)
150
+
151
+ const isDbReady = useIsDbReady()
152
+
153
+ const modelNameRef = useRef<string | undefined>(modelName)
154
+
155
+ const readFromDb = useCallback(
156
+ async (event) => {
157
+ if (
158
+ !event ||
159
+ !event.modelName ||
160
+ event.modelName !== modelNameRef.current ||
161
+ isReadingDb
162
+ ) {
163
+ return
164
+ }
165
+ setIsReadingDb(true)
166
+ const allItems = await Item.all(modelNameRef.current, deleted)
167
+ setItems(() => allItems)
168
+ setIsReadingDb(false)
169
+ },
170
+ [modelName, isReadingDb],
171
+ )
172
+
173
+ useEffect(() => {
174
+ if (isDbReady && !isInitialized) {
175
+ const _fetchItems = async (): Promise<void> => {
176
+ await readFromDb({ modelName })
177
+ setIsInitialized(true)
178
+ }
179
+
180
+ _fetchItems()
181
+ }
182
+ }, [isInitialized, isDbReady])
183
+
184
+ useEffect(() => {
185
+ eventEmitter.addListener('item.requestAll', readFromDb)
186
+
187
+ return () => {
188
+ eventEmitter.removeListener('item.requestAll')
189
+ }
190
+ }, [])
191
+
192
+ return {
193
+ items: orderBy(
194
+ items,
195
+ [
196
+ (item) =>
197
+ item.lastVersionPublishedAt ||
198
+ item.attestationCreatedAt ||
199
+ item.createdAt,
200
+ ],
201
+ ['desc'],
202
+ ).slice(0, 10),
203
+ isReadingDb,
204
+ isInitialized,
205
+ }
206
+ }
207
+ export const useItemIsReady = () => {
208
+ const [itemListenersReady, setItemListenersReady] = useState(false)
209
+
210
+ const itemEventListenersHandler = useCallback((_) => {
211
+ setItemListenersReady(true)
212
+ }, [])
213
+
214
+ useEffect(() => {
215
+ const areReady = getAreItemEventHandlersReady()
216
+
217
+ if (areReady) {
218
+ itemEventListenersHandler(true)
219
+ }
220
+
221
+ eventEmitter.addListener(
222
+ 'item.events.setupAllItemsEventHandlers',
223
+ itemEventListenersHandler,
224
+ )
225
+
226
+ return () => {
227
+ eventEmitter.removeListener('item.events.setupAllItemsEventHandlers')
228
+ }
229
+ }, [])
230
+
231
+ return {
232
+ isReady: itemListenersReady,
233
+ }
234
+ }
235
+ export const useCreateItem = <T>(modelName: string) => {
236
+ const [isCreatingItem, setIsCreatingItem] = useState(false)
237
+
238
+ const { isReady } = useItemIsReady()
239
+
240
+ const createItem = useCallback(
241
+ async (itemData) => {
242
+ if (!isReady) {
243
+ console.error(
244
+ `[useCreateItem] [createItem] called before listeners are ready`,
245
+ itemData,
246
+ )
247
+ return
248
+ }
249
+ if (isCreatingItem) {
250
+ // TODO: should we setup a queue for this?
251
+ console.error(
252
+ `[useCreateItem] [createItem] already creating item`,
253
+ itemData,
254
+ )
255
+ return
256
+ }
257
+
258
+ setIsCreatingItem(true)
259
+
260
+ const { seedLocalId } = await createNewItem({ modelName, ...itemData })
261
+
262
+ const newItem = await Item.find({ modelName, seedLocalId })
263
+
264
+ eventEmitter.emit('item.requestAll', { modelName })
265
+
266
+ setIsCreatingItem(false)
267
+ },
268
+ [isCreatingItem, isReady],
269
+ )
270
+
271
+ return {
272
+ createItem,
273
+ isCreatingItem,
274
+ }
275
+ }
276
+
277
+ type PublishItemResult = Error | undefined | void
278
+
279
+ type UsePublishItemReturn = {
280
+ publishItem: (
281
+ item: Item<any> | undefined,
282
+ callback: (result: PublishItemResult) => any,
283
+ ) => void
284
+ isPublishing: boolean
285
+ }
286
+
287
+ type PublishItemProps = [
288
+ item: Item<any> | undefined,
289
+ callback?: (result: PublishItemResult) => any | undefined,
290
+ ]
291
+
292
+ type PublishItem = (...props: PublishItemProps) => Promise<any>
293
+
294
+ export const usePublishItem = (): UsePublishItemReturn => {
295
+ const [isPublishing, setIsPublishing] = useState(false)
296
+
297
+ const isLocked = useRef(false)
298
+
299
+ const publishItem: PublishItem = useCallback(async (item, callback?) => {
300
+ if (!item || isLocked.current) {
301
+ return
302
+ }
303
+ isLocked.current = true
304
+ console.log('Publishing item', item)
305
+ setIsPublishing(true)
306
+ try {
307
+ await item.publish()
308
+ if (callback) {
309
+ callback()
310
+ }
311
+ } catch (e) {
312
+ if (callback) {
313
+ callback(e as Error)
314
+ }
315
+ }
316
+ setIsPublishing(false)
317
+ isLocked.current = false
318
+ }, [])
319
+
320
+ return {
321
+ publishItem,
322
+ isPublishing,
323
+ }
324
+ }
@@ -0,0 +1,158 @@
1
+ import { assign, setup } from 'xstate'
2
+ import { MachineIds } from '@/browser/services/internal/constants'
3
+ import { AllItemsMachineContext } from '@/types'
4
+ import { eventEmitter } from '@/eventBus'
5
+ import { initialize } from '@/browser/item/all/actors/initialize'
6
+ import { fetchDbData } from '@/browser/item/all/actors/fetchDbData'
7
+ import { fetchSeeds } from '@/browser/item/all/actors/fetchSeeds'
8
+ import { fetchVersions } from '@/browser/item/all/actors/fetchVersions'
9
+ import { fetchRelatedItems } from '@/browser/item/all/actors/fetchRelatedItems'
10
+ import { processItems } from '@/browser/item/all/actors/processItems'
11
+
12
+ const excludedVersionUidValues = ['', 'undefined', 'null', '0', 0]
13
+
14
+ export const itemMachineAll = setup({
15
+ types: {
16
+ context: {} as Partial<AllItemsMachineContext>,
17
+ input: {} as Partial<AllItemsMachineContext> | undefined,
18
+ },
19
+ actors: {
20
+ initialize,
21
+ fetchDbData,
22
+ fetchSeeds,
23
+ fetchVersions,
24
+ fetchRelatedItems,
25
+ processItems,
26
+ },
27
+ }).createMachine({
28
+ id: MachineIds.ALL_ITEMS,
29
+ initial: 'uninitialized',
30
+ context: ({ input }) => input as AllItemsMachineContext,
31
+ on: {
32
+ updateTimes: {
33
+ actions: assign({
34
+ times: ({ event }) => event.times,
35
+ }),
36
+ },
37
+ },
38
+ states: {
39
+ idle: {
40
+ entry: ({ self, context }) => {
41
+ eventEmitter.emit('service.saveState.request', {
42
+ state: self.getPersistedSnapshot(),
43
+ serviceId: `${MachineIds.ALL_ITEMS}_${context.modelName}`,
44
+ })
45
+ },
46
+ },
47
+ uninitialized: {
48
+ on: {
49
+ modelsFound: {
50
+ target: 'initializing',
51
+ actions: assign({
52
+ modelAddedToDb: true,
53
+ }),
54
+ },
55
+ },
56
+ },
57
+ initializing: {
58
+ on: {
59
+ initializeSuccess: {
60
+ target: 'fetchingSeeds',
61
+ actions: assign({
62
+ modelName: ({ event }) => event.modelName,
63
+ modelNameLowercase: ({ event }) => event.modelNameLowercase,
64
+ modelNamePlural: ({ event }) => event.modelNamePlural,
65
+ queryVariables: ({ event }) => event.queryVariables,
66
+ }),
67
+ },
68
+ modelsNotFound: 'idle',
69
+ },
70
+ invoke: {
71
+ src: 'initialize',
72
+ input: ({ context }) => ({ context }),
73
+ },
74
+ },
75
+ fetchingSeeds: {
76
+ on: {
77
+ fetchSeedsSuccess: {
78
+ target: 'fetchingVersions',
79
+ actions: assign({
80
+ itemSeeds: ({ event }) => event.itemSeeds,
81
+ }),
82
+ },
83
+ },
84
+ invoke: {
85
+ src: 'fetchSeeds',
86
+ input: ({ context }) => ({ context }),
87
+ },
88
+ },
89
+ fetchingVersions: {
90
+ on: {
91
+ fetchVersionsSuccess: {
92
+ target: 'fetchingRelatedItems',
93
+ actions: assign({
94
+ itemVersions: ({ event }) => event.itemVersions,
95
+ }),
96
+ },
97
+ },
98
+ invoke: {
99
+ src: 'fetchVersions',
100
+ input: ({ context }) => ({ context }),
101
+ },
102
+ },
103
+ fetchingRelatedItems: {
104
+ on: {
105
+ fetchRelatedItemsSuccess: {
106
+ target: 'processingItems',
107
+ actions: assign({
108
+ relatedProperties: ({ event }) => event.relatedProperties,
109
+ relatedVersionsBySeedUid: ({ event }) =>
110
+ event.relatedVersionsBySeedUid,
111
+ relatedVersionsBySchemaUid: ({ event }) =>
112
+ event.relatedVersionsBySchemaUid,
113
+ schemaUidsByModelName: ({ event }) => event.schemaUidsByModelName,
114
+ mostRecentPropertiesBySeedUid: ({ event }) =>
115
+ event.mostRecentPropertiesBySeedUid,
116
+ }),
117
+ },
118
+ },
119
+ invoke: {
120
+ src: 'fetchRelatedItems',
121
+ input: ({ context }) => ({ context }),
122
+ },
123
+ },
124
+ processingItems: {
125
+ on: {
126
+ processItemsSuccess: 'idle',
127
+ itemCreated: {
128
+ actions: assign({
129
+ items: ({ context, event }) => {
130
+ if (context && context.items) {
131
+ const foundItem = context.items.find((item) => {
132
+ if (!item.versionLocalId) {
133
+ return false
134
+ }
135
+ return (
136
+ item.versionLocalId === event.item.versionLocalId ||
137
+ item.versionUid === event.item.versionUid
138
+ )
139
+ })
140
+ if (foundItem) {
141
+ return context.items
142
+ }
143
+ return [...context.items, event.item]
144
+ }
145
+ if (context && !context.items) {
146
+ return [event.item]
147
+ }
148
+ },
149
+ }),
150
+ },
151
+ },
152
+ invoke: {
153
+ src: 'processItems',
154
+ input: ({ context, self }) => ({ context, self }),
155
+ },
156
+ },
157
+ },
158
+ })
@@ -0,0 +1,175 @@
1
+ import { assign, setup } from 'xstate'
2
+ import { MachineIds } from '@/browser/services/internal/constants'
3
+ import { ItemMachineContext } from '@/types'
4
+ import { ItemProperty } from '../../property'
5
+ import { waitForDb } from './actors/waitForDb'
6
+ import { initialize } from './actors/initialize'
7
+ import { hydrateExistingItem } from './actors/hydrateExistingItem'
8
+ import { hydrateNewItem } from './actors/hydrateNewItem'
9
+ import { fetchDataFromEas } from './actors/fetchDataFromEas'
10
+
11
+ export const itemMachineSingle = setup({
12
+ types: {
13
+ context: {} as ItemMachineContext<any>,
14
+ input: {},
15
+ },
16
+ actors: {
17
+ waitForDb,
18
+ initialize,
19
+ hydrateExistingItem,
20
+ hydrateNewItem,
21
+ fetchDataFromEas,
22
+ },
23
+ }).createMachine({
24
+ id: MachineIds.ITEM,
25
+ initial: 'waitingForDb',
26
+ context: ({ input }) => input as ItemMachineContext<any>,
27
+ on: {
28
+ updatedPropertiesBySchemaUid: {
29
+ actions: assign({
30
+ propertiesBySchemaUid: ({ event }) => event.propertiesBySchemaUid,
31
+ }),
32
+ },
33
+ updatePropertiesMetadata: {
34
+ actions: assign({
35
+ propertiesMetadata: ({ event }) => event.propertiesMetadata,
36
+ }),
37
+ },
38
+ updateProperties: {
39
+ actions: assign({
40
+ propertiesUpdatedAt: Date.now(),
41
+ }),
42
+ },
43
+ updateValue: {
44
+ actions: assign(({ event, context }) => {
45
+ let { propertyInstances } = context
46
+ if (!propertyInstances) {
47
+ propertyInstances = new Map<string, ItemProperty<any>>()
48
+ }
49
+ const { propertyName, propertyValue } = event
50
+
51
+ if (!propertyInstances.has(propertyName)) {
52
+ return {
53
+ [propertyName]: propertyValue,
54
+ }
55
+ }
56
+ const propertyInstance = propertyInstances.get(
57
+ propertyName,
58
+ ) as ItemProperty<any>
59
+
60
+ propertyInstance.value = propertyValue
61
+ propertyInstances.set(propertyName, propertyInstance)
62
+ // TODO: use immer here
63
+ return {
64
+ propertyInstances,
65
+ }
66
+ }),
67
+ },
68
+ addPropertyInstance: {
69
+ actions: assign(({ context, event }) => {
70
+ const propertyInstances =
71
+ context.propertyInstances || new Map<string, typeof ItemProperty>()
72
+ propertyInstances.set(event.propertyName, event.propertyInstance)
73
+ return {
74
+ propertyInstances,
75
+ }
76
+ }),
77
+ },
78
+ // addPropertyAttestation: {
79
+ // actions: assign(({ context, event }) => {
80
+ // console.log('[singleItemMachine] [addPropertyAttestation] event', event)
81
+ // const propertyInstances =
82
+ // context.propertyInstances || new Map<string, typeof ItemProperty>()
83
+ // propertyInstances.set(event.propertyName, event.propertyInstances)
84
+ // return {
85
+ // propertyInstances,
86
+ // }
87
+ // }),
88
+ // },
89
+ },
90
+ states: {
91
+ idle: {},
92
+ waitingForDb: {
93
+ on: {
94
+ waitForDbSuccess: 'initializing',
95
+ },
96
+ invoke: {
97
+ src: 'waitForDb',
98
+ },
99
+ },
100
+ initializing: {
101
+ on: {
102
+ hasExistingItem: {
103
+ target: 'idle',
104
+ actions: assign({
105
+ modelTableName: ({ event }) => event.modelTableName,
106
+ modelNamePlural: ({ event }) => event.modelNamePlural,
107
+ modelName: ({ event }) => event.modelName,
108
+ existingItem: ({ event }) => event.existingItem,
109
+ }),
110
+ },
111
+ isNewItem: {
112
+ target: 'idle',
113
+ actions: assign({
114
+ modelTableName: ({ event }) => event.modelTableName,
115
+ modelNamePlural: ({ event }) => event.modelNamePlural,
116
+ modelName: ({ event }) => event.modelName,
117
+ }),
118
+ },
119
+ },
120
+ invoke: {
121
+ src: 'initialize',
122
+ input: ({ context, event }) => ({ context, event }),
123
+ },
124
+ },
125
+ hydratingExistingItem: {
126
+ on: {
127
+ hydrateExistingItemSuccess: 'idle',
128
+ hydrateExistingItemFailure: 'destroying',
129
+ },
130
+ invoke: {
131
+ src: 'hydrateExistingItem',
132
+ input: ({ event, context }) => ({ event, context }),
133
+ },
134
+ },
135
+ hydratingNewItem: {
136
+ on: {
137
+ hydrateNewItemSuccess: 'idle',
138
+ },
139
+ invoke: {
140
+ src: 'hydrateNewItem',
141
+ input: ({ context }) => ({ context }),
142
+ },
143
+ },
144
+ fetchingRemoteData: {
145
+ on: {
146
+ fetchRemoteDataSuccess: 'idle',
147
+ },
148
+ invoke: {
149
+ src: 'fetchRemoteData',
150
+ input: ({ context }) => ({ context }),
151
+ },
152
+ },
153
+ // fetchingDataFromEas: {
154
+ // on: {
155
+ // fetchDataFromEasSuccess: 'savingDataToDb',
156
+ // },
157
+ // invoke: {
158
+ // src: 'fetchDataFromEas',
159
+ // input: ({ context }) => ({ context }),
160
+ // },
161
+ // },
162
+ // savingDataToDb: {
163
+ // on: {
164
+ // saveDataToDbSuccess: 'idle',
165
+ // },
166
+ // invoke: {
167
+ // src: 'saveDataToDb',
168
+ // input: ({ context }) => ({ context }),
169
+ // },
170
+ // },
171
+ destroying: {
172
+ type: 'final',
173
+ },
174
+ },
175
+ })
@@ -0,0 +1,47 @@
1
+ import { EventObject, fromCallback, Subscription } from 'xstate'
2
+ import {
3
+ DB_NAME_APP,
4
+ DB_ON_SNAPSHOT,
5
+ INTERNAL_LOADING_APP_DB_SUCCESS,
6
+ } from '@/browser/services/internal/constants'
7
+ import debug from 'debug'
8
+ import { FromCallbackInput, InternalMachineContext } from '@/types'
9
+
10
+ const logger = debug('app:services:internal:actors:loadAppDb')
11
+
12
+ export const loadAppDb = fromCallback<
13
+ EventObject,
14
+ FromCallbackInput<InternalMachineContext>
15
+ >(({ sendBack, input: { context } }) => {
16
+ const { appDbService } = context
17
+
18
+ let subscription: Subscription | undefined
19
+
20
+ const _loadAppDb = async (): Promise<void> => {
21
+ return new Promise((resolve) => {
22
+ if (appDbService.getSnapshot().value === 'ready') {
23
+ return resolve()
24
+ }
25
+ subscription = appDbService.subscribe({
26
+ next: (snapshot) => {
27
+ if (snapshot.value === 'ready') {
28
+ return resolve()
29
+ }
30
+
31
+ sendBack({ type: DB_ON_SNAPSHOT, dbName: DB_NAME_APP, snapshot })
32
+ },
33
+ })
34
+ })
35
+ }
36
+
37
+ _loadAppDb().then(() => {
38
+ sendBack({ type: INTERNAL_LOADING_APP_DB_SUCCESS })
39
+ logger('[sdk] [internal/actors] Successfully loaded app DB')
40
+ })
41
+
42
+ return () => {
43
+ if (subscription) {
44
+ subscription.unsubscribe()
45
+ }
46
+ }
47
+ })