@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.
- package/dist/bin.js.map +1 -1
- package/dist/constants-BLctWkrn.js.map +1 -1
- package/dist/{index-DWf9Ls94.js → index-DMIKRod-.js} +3995 -3995
- package/dist/index-DMIKRod-.js.map +1 -0
- package/dist/{index-B2WbNudj.js → index-wKss7188.js} +10 -10
- package/dist/index-wKss7188.js.map +1 -0
- package/dist/main.js +7 -7
- package/dist/{seed.schema.config-mBqth17w.js → seed.schema.config-C0M8Rcti.js} +7 -7
- package/dist/seed.schema.config-C0M8Rcti.js.map +1 -0
- package/dist/src/AppStateSchema.ts +10 -0
- package/dist/src/Attestation.ts +21 -0
- package/dist/src/ConfigSchema.ts +15 -0
- package/dist/src/ItemProperty.ts +383 -0
- package/dist/src/MetadataSchema.ts +28 -0
- package/dist/src/ModelSchema.ts +46 -0
- package/dist/src/ModelUidSchema.ts +16 -0
- package/dist/src/PropertyUidSchema.ts +16 -0
- package/dist/src/Schema.ts +17 -0
- package/dist/src/SeedSchema.ts +29 -0
- package/dist/src/VersionSchema.ts +16 -0
- package/dist/src/actors.ts +280 -0
- package/dist/src/addModelsToDb.ts +150 -0
- package/dist/src/allItems.ts +23 -0
- package/dist/src/arweave.ts +37 -0
- package/dist/src/browser.app.db.config.ts +27 -0
- package/dist/src/browser.seed.db.config.ts +33 -0
- package/dist/src/browser.ts +30 -0
- package/dist/src/checkStatus.ts +50 -0
- package/dist/src/client.ts +85 -0
- package/dist/src/configureFs.ts +81 -0
- package/dist/src/connectToDb.ts +74 -0
- package/dist/src/connectionManager.ts +67 -0
- package/dist/src/constants.ts +118 -0
- package/dist/src/create.ts +39 -0
- package/dist/src/createItem.ts +15 -0
- package/dist/src/createItemMachine.ts +37 -0
- package/dist/src/createPublishAttempt.ts +16 -0
- package/dist/src/createSeeds.ts +24 -0
- package/dist/src/createVersion.ts +33 -0
- package/dist/src/db.ts +247 -0
- package/dist/src/dbMachine.ts +181 -0
- package/dist/src/deleteItem.ts +19 -0
- package/dist/src/download.ts +289 -0
- package/dist/src/drizzle.ts +82 -0
- package/dist/src/environment.ts +15 -0
- package/dist/src/eventBus.ts +5 -0
- package/dist/src/events.ts +14 -0
- package/dist/src/fetchDataFromEas.ts +90 -0
- package/dist/src/fetchDbData.ts +16 -0
- package/dist/src/fetchRelatedItems.ts +179 -0
- package/dist/src/fetchSeeds.ts +44 -0
- package/dist/src/fetchVersions.ts +41 -0
- package/dist/src/files.ts +16 -0
- package/dist/src/fragment-masking.ts +87 -0
- package/dist/src/fsProxy.ts +36 -0
- package/dist/src/getItem.ts +189 -0
- package/dist/src/getItemProperties.ts +162 -0
- package/dist/src/getItems.ts +75 -0
- package/dist/src/getMetadata.ts +40 -0
- package/dist/src/getModelSchemas.ts +88 -0
- package/dist/src/getSchemaForModel.ts +42 -0
- package/dist/src/getSeedData.ts +34 -0
- package/dist/src/getVersionData.ts +58 -0
- package/dist/src/getVersionsForVersionUids.ts +39 -0
- package/dist/src/globalMachine.ts +259 -0
- package/dist/src/gql.ts +113 -0
- package/dist/src/graphql.ts +3201 -0
- package/dist/src/helpers.ts +150 -0
- package/dist/src/hydrateExistingItem.ts +137 -0
- package/dist/src/hydrateFromDb.ts +254 -0
- package/dist/src/hydrateNewItem.ts +34 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.ts +73 -0
- package/dist/src/init.ts +61 -0
- package/dist/src/initialize.ts +127 -0
- package/dist/src/internalMachine.ts +220 -0
- package/dist/src/item.ts +324 -0
- package/dist/src/itemMachineAll.ts +158 -0
- package/dist/src/itemMachineSingle.ts +175 -0
- package/dist/src/loadAppDb.ts +47 -0
- package/dist/src/logger.ts +33 -0
- package/dist/src/machine.ts +55 -0
- package/dist/src/machines.ts +58 -0
- package/dist/src/migrate.ts +288 -0
- package/dist/src/model.ts +71 -0
- package/dist/src/modelClass.ts +19 -0
- package/dist/src/node.app.db.config.ts +40 -0
- package/dist/src/prepareDb.ts +34 -0
- package/dist/src/preparePublishRequestData.ts +81 -0
- package/dist/src/processItems.ts +71 -0
- package/dist/src/property.ts +161 -0
- package/dist/src/propertyMachine.ts +154 -0
- package/dist/src/publish.ts +31 -0
- package/dist/src/publishMachine.ts +77 -0
- package/dist/src/queries.ts +13 -0
- package/dist/src/read.ts +174 -0
- package/dist/src/recoverDeletedItem.ts +14 -0
- package/dist/src/request.ts +54 -0
- package/dist/src/requestAll.ts +157 -0
- package/dist/src/resolveRelatedValue.ts +348 -0
- package/dist/src/resolveRemoteStorage.ts +87 -0
- package/dist/src/save.ts +183 -0
- package/dist/src/saveConfig.ts +79 -0
- package/dist/src/saveDataToDb.ts +145 -0
- package/dist/src/saveMetadata.ts +18 -0
- package/dist/src/saveValueToDb.ts +94 -0
- package/dist/src/seed.schema.config.ts +25 -0
- package/dist/src/seed.ts +37 -0
- package/dist/src/seedData.ts +0 -0
- package/dist/src/seedProtocol.ts +17 -0
- package/dist/src/services.ts +359 -0
- package/dist/src/sqlWasmClient.ts +88 -0
- package/dist/src/syncDbWithEas.ts +686 -0
- package/dist/src/trash.ts +29 -0
- package/dist/src/ts-to-proto.ts +101 -0
- package/dist/src/types.ts +12 -0
- package/dist/src/upload.ts +86 -0
- package/dist/src/validate.ts +42 -0
- package/dist/src/validateInput.ts +33 -0
- package/dist/src/validateItemData.ts +20 -0
- package/dist/src/waitForDb.ts +23 -0
- package/dist/src/wasm.d.ts +8300 -0
- package/dist/src/write.ts +366 -0
- package/dist/types/src/browser/db/read/getModelSchemas.d.ts.map +1 -1
- package/dist/types/src/browser/item/single/actors/hydrateExistingItem.d.ts +3 -1
- package/dist/types/src/browser/item/single/actors/hydrateExistingItem.d.ts.map +1 -1
- package/dist/types/src/browser/item/single/actors/saveDataToDb.d.ts +3 -3
- package/dist/types/src/browser/item/single/itemMachineSingle.d.ts +3 -3
- package/dist/types/src/browser/property/ItemProperty.d.ts +7 -7
- package/dist/types/src/browser/property/ItemProperty.d.ts.map +1 -1
- package/dist/types/src/browser/property/actors/resolveRemoteStorage.d.ts +3 -3
- package/dist/types/src/browser/react/trash.d.ts +1 -1
- package/dist/types/src/browser/react/trash.d.ts.map +1 -1
- package/dist/types/src/browser/services/db/dbMachine.d.ts +6 -6
- package/dist/types/src/browser/services/publish/publishMachine.d.ts +17 -17
- package/dist/types/src/types/machines.d.ts +4 -0
- package/dist/types/src/types/machines.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/index-B2WbNudj.js.map +0 -1
- package/dist/index-DWf9Ls94.js.map +0 -1
- package/dist/seed.schema.config-mBqth17w.js.map +0 -1
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { syncDbFiles } from '@/browser/services/internal/helpers'
|
|
2
|
+
import { eventEmitter } from '@/eventBus'
|
|
3
|
+
import { fs } from '@zenfs/core'
|
|
4
|
+
import { ARWEAVE_HOST } from '@/browser/services/internal/constants'
|
|
5
|
+
import { appState } from 'src/shared/seedSchema'
|
|
6
|
+
import { eq } from 'drizzle-orm'
|
|
7
|
+
import { getArweave } from '@/browser/schema/file'
|
|
8
|
+
import { getAddressesFromDb } from '@/shared/helpers/db'
|
|
9
|
+
import { getImageDataType, getMimeType, identifyString } from '@/shared/helpers'
|
|
10
|
+
import { arweaveClient, easClient, queryClient } from '@/browser/helpers'
|
|
11
|
+
import { GET_FILES_METADATA } from '@/browser/schema/file/queries'
|
|
12
|
+
import debug from 'debug'
|
|
13
|
+
import { getAppDb, isAppDbReady } from '@/browser/db/sqlWasmClient'
|
|
14
|
+
import { getGlobalService } from '@/browser/services'
|
|
15
|
+
import { waitFor } from 'xstate'
|
|
16
|
+
import { writeAppState } from '@/browser/db/write'
|
|
17
|
+
import { getMetadata } from '@/browser/db/read/getMetadata'
|
|
18
|
+
import { saveMetadata } from '@/browser/db/write/saveMetadata'
|
|
19
|
+
import { GET_TRANSACTION_TAGS } from '@/browser/arweave/queries'
|
|
20
|
+
|
|
21
|
+
const logger = debug('app:files:download')
|
|
22
|
+
|
|
23
|
+
export const downloadAllFilesRequestHandler = async ({
|
|
24
|
+
endpoints,
|
|
25
|
+
eventId,
|
|
26
|
+
}) => {
|
|
27
|
+
await syncDbFiles(endpoints)
|
|
28
|
+
|
|
29
|
+
eventEmitter.emit('fs.downloadAll.success', { eventId })
|
|
30
|
+
eventEmitter.emit('fs.downloadAllBinary.request', { endpoints })
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const downloadAllFilesBinaryRequestHandler = async () => {
|
|
34
|
+
let addresses: string[] | undefined
|
|
35
|
+
|
|
36
|
+
if (isAppDbReady()) {
|
|
37
|
+
addresses = await getAddressesFromDb()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!isAppDbReady()) {
|
|
41
|
+
const globalService = getGlobalService()
|
|
42
|
+
const internalService = globalService.getSnapshot().context.internalService
|
|
43
|
+
if (internalService) {
|
|
44
|
+
await waitFor(internalService, (snapshot) => snapshot.value === 'ready')
|
|
45
|
+
addresses = await getAddressesFromDb()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!addresses || addresses.length === 0) {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const { filesMetadata } = await queryClient.fetchQuery({
|
|
54
|
+
queryKey: ['getFilesMetadata', ...addresses],
|
|
55
|
+
queryFn: async () =>
|
|
56
|
+
easClient.request(GET_FILES_METADATA, {
|
|
57
|
+
where: {
|
|
58
|
+
attester: {
|
|
59
|
+
in: addresses,
|
|
60
|
+
},
|
|
61
|
+
schema: {
|
|
62
|
+
is: {
|
|
63
|
+
id: {
|
|
64
|
+
equals:
|
|
65
|
+
'0x55fdefb36fcbbaebeb7d6b41dc3a1a9666e4e42154267c889de064faa7ede517',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
}),
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
if (!(await fs.promises.exists('/files'))) {
|
|
74
|
+
await fs.promises.mkdir('/files', { recursive: true })
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!(await fs.promises.exists('/files/html'))) {
|
|
78
|
+
await fs.promises.mkdir('/files/html', { recursive: true })
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!(await fs.promises.exists('/files/json'))) {
|
|
82
|
+
await fs.promises.mkdir('/files/json', { recursive: true })
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!(await fs.promises.exists('/files/images'))) {
|
|
86
|
+
await fs.promises.mkdir('/files/images', { recursive: true })
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const appDb = getAppDb()
|
|
90
|
+
|
|
91
|
+
if (!appDb) {
|
|
92
|
+
console.warn('[fetchAll/actors] [fetchAllBinaryData] seedDb not available')
|
|
93
|
+
return []
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
for (const fileMetadata of filesMetadata) {
|
|
97
|
+
const json = JSON.parse(fileMetadata.decodedDataJson)
|
|
98
|
+
const transactionId = json[0].value.value
|
|
99
|
+
|
|
100
|
+
const excludedTransactionsQuery = await appDb
|
|
101
|
+
.select()
|
|
102
|
+
.from(appState)
|
|
103
|
+
.where(eq(appState.key, 'excludedTransactions'))
|
|
104
|
+
|
|
105
|
+
let excludedTransactions = new Set<string>()
|
|
106
|
+
|
|
107
|
+
if (excludedTransactionsQuery && excludedTransactionsQuery.length === 1) {
|
|
108
|
+
const valueString = excludedTransactionsQuery[0].value
|
|
109
|
+
if (valueString) {
|
|
110
|
+
const excludedTransactionsArray = JSON.parse(valueString)
|
|
111
|
+
excludedTransactions = new Set(excludedTransactionsArray)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (excludedTransactions.has(transactionId)) {
|
|
116
|
+
continue
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const arweave = getArweave()
|
|
120
|
+
|
|
121
|
+
if (!arweave) {
|
|
122
|
+
console.warn(
|
|
123
|
+
'[fetchAll/actors] [fetchAllBinaryData] arweave not available',
|
|
124
|
+
)
|
|
125
|
+
return []
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
const res = await fetch(
|
|
130
|
+
`https://${ARWEAVE_HOST}/tx/${transactionId}/status`,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
if (res.status !== 200) {
|
|
134
|
+
logger(
|
|
135
|
+
`[fetchAll/actors] [fetchAllBinaryData] error fetching transaction data for ${transactionId}`,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
excludedTransactions.add(transactionId)
|
|
139
|
+
|
|
140
|
+
await writeAppState(
|
|
141
|
+
'excludedTransactions',
|
|
142
|
+
JSON.stringify(Array.from(excludedTransactions)),
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
continue
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const { tags } = await queryClient.fetchQuery({
|
|
149
|
+
queryKey: ['getTransactionTags', transactionId],
|
|
150
|
+
queryFn: async () =>
|
|
151
|
+
arweaveClient.request(GET_TRANSACTION_TAGS, {
|
|
152
|
+
transactionId,
|
|
153
|
+
}),
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
if (tags && tags.length === 0) {
|
|
157
|
+
for (const { name, value } of tags) {
|
|
158
|
+
if (name === 'Content-SHA-256') {
|
|
159
|
+
const metadataRecord = await getMetadata({
|
|
160
|
+
storageTransactionId: transactionId,
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
if (metadataRecord) {
|
|
164
|
+
await saveMetadata(metadataRecord, {
|
|
165
|
+
contentHash: value,
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const fetchResponse = await queryClient.fetchQuery({
|
|
173
|
+
queryKey: ['fetchTransaction', transactionId],
|
|
174
|
+
queryFn: async () =>
|
|
175
|
+
fetch(`https://${ARWEAVE_HOST}/raw/${transactionId}`),
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
const dataString = await fetchResponse.text()
|
|
179
|
+
|
|
180
|
+
// const dataString = await arweave.transactions.getData(transactionId, {
|
|
181
|
+
// decode: true,
|
|
182
|
+
// string: true,
|
|
183
|
+
// })
|
|
184
|
+
|
|
185
|
+
if (!dataString) {
|
|
186
|
+
logger(
|
|
187
|
+
`[fetchAll/actors] [fetchAllBinaryData] transaction ${transactionId} data not found`,
|
|
188
|
+
)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
let contentType = identifyString(dataString)
|
|
192
|
+
if (
|
|
193
|
+
contentType !== 'json' &&
|
|
194
|
+
contentType !== 'base64' &&
|
|
195
|
+
contentType !== 'html'
|
|
196
|
+
) {
|
|
197
|
+
const possibleImageType = getImageDataType(dataString)
|
|
198
|
+
if (!possibleImageType) {
|
|
199
|
+
logger(
|
|
200
|
+
`[fetchAll/actors] [fetchAllBinaryData] transaction ${transactionId} data not in expected format: ${possibleImageType}`,
|
|
201
|
+
)
|
|
202
|
+
continue
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
contentType = possibleImageType
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (contentType === 'url') {
|
|
209
|
+
const url = dataString as string
|
|
210
|
+
const response = await fetch(url)
|
|
211
|
+
if (!response.ok) {
|
|
212
|
+
throw new Error(`Failed to fetch image: ${response.statusText}`)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Get the image as a Blob
|
|
216
|
+
const blob = await response.blob()
|
|
217
|
+
const buffer = await blob.arrayBuffer()
|
|
218
|
+
const bufferUint8Array = new Uint8Array(buffer)
|
|
219
|
+
|
|
220
|
+
// Extract the file extension from the URL
|
|
221
|
+
const extensionMatch = url.match(/\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i)
|
|
222
|
+
if (!extensionMatch) {
|
|
223
|
+
throw new Error(
|
|
224
|
+
'Unable to determine the file extension from the URL.',
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
const fileExtension = extensionMatch[0] // e.g., ".jpg"
|
|
228
|
+
|
|
229
|
+
// Set the file name (you can customize this)
|
|
230
|
+
// const fileNameFromUrl = `${transactionId}${fileExtension}`
|
|
231
|
+
|
|
232
|
+
await fs.promises.writeFile(
|
|
233
|
+
`/files/images/${transactionId}`,
|
|
234
|
+
bufferUint8Array,
|
|
235
|
+
{
|
|
236
|
+
encoding: 'binary',
|
|
237
|
+
},
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
continue
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const mimeType = getMimeType(dataString as string)
|
|
244
|
+
|
|
245
|
+
let fileName = transactionId
|
|
246
|
+
|
|
247
|
+
if (contentType === 'base64') {
|
|
248
|
+
if (mimeType) {
|
|
249
|
+
fileName += `.${mimeType}`
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Remove the Base64 header if it exists (e.g., "data:image/png;base64,")
|
|
253
|
+
const base64Data = dataString.split(',').pop() || ''
|
|
254
|
+
|
|
255
|
+
// Decode the Base64 string to binary
|
|
256
|
+
const binaryString = atob(base64Data)
|
|
257
|
+
const length = binaryString.length
|
|
258
|
+
const binaryData = new Uint8Array(length)
|
|
259
|
+
|
|
260
|
+
for (let i = 0; i < length; i++) {
|
|
261
|
+
binaryData[i] = binaryString.charCodeAt(i)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
await fs.promises.writeFile(`/files/images/${fileName}`, binaryData, {
|
|
265
|
+
encoding: 'binary',
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
// if (dataUint8Array && dataUint8Array instanceof Uint8Array) {
|
|
269
|
+
// await fs.promises.writeFile(
|
|
270
|
+
// `/files/images/${fileName}`,
|
|
271
|
+
// dataUint8Array,
|
|
272
|
+
// )
|
|
273
|
+
// }
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (contentType === 'html') {
|
|
277
|
+
fileName += '.html'
|
|
278
|
+
await fs.promises.writeFile(`/files/html/${fileName}`, dataString)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (contentType === 'json') {
|
|
282
|
+
fileName += '.json'
|
|
283
|
+
await fs.promises.writeFile(`/files/json/${fileName}`, dataString)
|
|
284
|
+
}
|
|
285
|
+
} catch (error) {
|
|
286
|
+
logger(error)
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import pluralize from 'pluralize'
|
|
4
|
+
import { camelCase, snakeCase } from 'lodash-es'
|
|
5
|
+
import * as nunjucks from 'nunjucks'
|
|
6
|
+
import { ILoader } from 'nunjucks'
|
|
7
|
+
import { ModelClassType } from '@/types'
|
|
8
|
+
import { SCHEMA_NJK } from '@/shared/helpers/constants'
|
|
9
|
+
import {
|
|
10
|
+
appGeneratedSchemaDir,
|
|
11
|
+
dotSeedDir,
|
|
12
|
+
templatePath,
|
|
13
|
+
} from '@/node/constants'
|
|
14
|
+
import { getTsImport } from '@/node/helpers'
|
|
15
|
+
|
|
16
|
+
const TemplateLoader: ILoader = {
|
|
17
|
+
getSource: (name: string) => {
|
|
18
|
+
let templateFilePath
|
|
19
|
+
if (name.includes(templatePath)) {
|
|
20
|
+
templateFilePath = name
|
|
21
|
+
} else {
|
|
22
|
+
templateFilePath = path.join(templatePath, path.basename(name))
|
|
23
|
+
}
|
|
24
|
+
const src = fs.readFileSync(templateFilePath, 'utf-8')
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
path: name,
|
|
28
|
+
src,
|
|
29
|
+
noCache: false,
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Configure Nunjucks
|
|
35
|
+
const env = new nunjucks.Environment(TemplateLoader)
|
|
36
|
+
|
|
37
|
+
env.addFilter('camelCase', camelCase)
|
|
38
|
+
env.addFilter('snakeCase', snakeCase)
|
|
39
|
+
env.addFilter('pluralize', pluralize)
|
|
40
|
+
|
|
41
|
+
const generateDrizzleSchemaCode = (
|
|
42
|
+
modelName: string,
|
|
43
|
+
modelClass: ModelClassType,
|
|
44
|
+
): string => {
|
|
45
|
+
const listProperties = Object.entries(modelClass.schema).filter(
|
|
46
|
+
([key, propertyDef]) => propertyDef?.dataType === 'List',
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
const filePath = path.join(templatePath, SCHEMA_NJK)
|
|
50
|
+
|
|
51
|
+
const schemaCode = env.render(filePath, {
|
|
52
|
+
modelName,
|
|
53
|
+
modelClass,
|
|
54
|
+
listProperties,
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
return schemaCode
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const createDrizzleSchemaFilesFromConfig = async () => {
|
|
61
|
+
const schemaFilePath = path.join(dotSeedDir, 'schema.ts') // Developer created file with model definitions
|
|
62
|
+
|
|
63
|
+
console.log('schemaFilePath:', schemaFilePath)
|
|
64
|
+
|
|
65
|
+
const { models } = await getTsImport<{
|
|
66
|
+
models: Record<string, ModelClassType>
|
|
67
|
+
}>(schemaFilePath)
|
|
68
|
+
|
|
69
|
+
console.log('models:', models)
|
|
70
|
+
|
|
71
|
+
for (const [modelName, modelClass] of Object.entries(models)) {
|
|
72
|
+
const code = generateDrizzleSchemaCode(modelName, modelClass)
|
|
73
|
+
|
|
74
|
+
if (!fs.existsSync(appGeneratedSchemaDir)) {
|
|
75
|
+
fs.mkdirSync(appGeneratedSchemaDir)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const filePath = path.join(appGeneratedSchemaDir, `${modelName}Schema.ts`)
|
|
79
|
+
|
|
80
|
+
await fs.promises.writeFile(filePath, code).catch((e) => console.error(e))
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const isNode = (): boolean => {
|
|
2
|
+
return (
|
|
3
|
+
typeof process !== 'undefined' &&
|
|
4
|
+
process.versions != null &&
|
|
5
|
+
process.versions.node != null
|
|
6
|
+
)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const isBrowser = (): boolean => {
|
|
10
|
+
return typeof window !== 'undefined' && typeof window.document !== 'undefined'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const isReactNative = (): boolean => {
|
|
14
|
+
return typeof navigator !== 'undefined' && navigator.product === 'ReactNative'
|
|
15
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { eventEmitter } from '@/eventBus'
|
|
2
|
+
import debug from 'debug'
|
|
3
|
+
|
|
4
|
+
const logger = debug('app:services:events')
|
|
5
|
+
|
|
6
|
+
const handleServiceSaveState = (event: any) => {
|
|
7
|
+
const { state, serviceId } = event
|
|
8
|
+
logger(`[browser] [service.saveState.request] serviceId: ${serviceId}`)
|
|
9
|
+
localStorage.setItem(`seed_sdk_service_${serviceId}`, JSON.stringify(state))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const setupServicesEventHandlers = () => {
|
|
13
|
+
eventEmitter.addListener('service.saveState.request', handleServiceSaveState)
|
|
14
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { EventObject, fromCallback } from 'xstate'
|
|
2
|
+
import { GET_PROPERTIES } from '@/browser/item/queries'
|
|
3
|
+
import { itemMachineSingle } from '@/browser/item/single/itemMachineSingle'
|
|
4
|
+
import { PropertyType } from '@/shared/seedSchema'
|
|
5
|
+
import { easClient, queryClient } from '@/browser/helpers'
|
|
6
|
+
import { Attestation } from '@/browser/gql/graphql'
|
|
7
|
+
import { ModelClassType } from '@/types'
|
|
8
|
+
|
|
9
|
+
export const fetchDataFromEas = fromCallback<
|
|
10
|
+
EventObject,
|
|
11
|
+
typeof itemMachineSingle
|
|
12
|
+
>(({ sendBack, input: { context } }) => {
|
|
13
|
+
const { ModelClass, modelTableName, versionUid } = context
|
|
14
|
+
|
|
15
|
+
const propertiesMetadata = new Map<string, PropertyType>()
|
|
16
|
+
|
|
17
|
+
// EAS is the final source of truth, so we need to see if our Item is
|
|
18
|
+
// already represented there. Then we need to intelligently sync/merge
|
|
19
|
+
// with whatever new data has been created on the device before the sync.
|
|
20
|
+
for (const [propertyName, propertyMetadata] of Object.entries(
|
|
21
|
+
(ModelClass as ModelClassType).schema,
|
|
22
|
+
)) {
|
|
23
|
+
if (propertyMetadata) {
|
|
24
|
+
propertiesMetadata.set(propertyName, propertyMetadata)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
sendBack({ type: 'updatePropertiesMetadata', propertiesMetadata })
|
|
29
|
+
|
|
30
|
+
if (!versionUid) {
|
|
31
|
+
// In this case this is a local only item, so we don't need to fetch anything
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const _fetchDataFromEas = async (): Promise<void> => {
|
|
36
|
+
// Fetch Properties by versionUid
|
|
37
|
+
const { itemProperties } = await queryClient.fetchQuery({
|
|
38
|
+
queryKey: ['getProperties', versionUid],
|
|
39
|
+
queryFn: async () =>
|
|
40
|
+
easClient.request(GET_PROPERTIES, {
|
|
41
|
+
where: {
|
|
42
|
+
refUID: {
|
|
43
|
+
in: [versionUid],
|
|
44
|
+
},
|
|
45
|
+
decodedDataJson: {
|
|
46
|
+
not: {
|
|
47
|
+
// The first of many filters to keep bad data out
|
|
48
|
+
contains:
|
|
49
|
+
'"value":"0x0000000000000000000000000000000000000000000000000000000000000020"',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
}),
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
// Filter properties by schemaId
|
|
57
|
+
const selectedPropertiesMap: {
|
|
58
|
+
[schemaId: string]: Attestation[]
|
|
59
|
+
} = {}
|
|
60
|
+
itemProperties.forEach((property) => {
|
|
61
|
+
const existingProperties = selectedPropertiesMap[property.schemaId] || []
|
|
62
|
+
existingProperties.push(property)
|
|
63
|
+
selectedPropertiesMap[property.schemaId] = existingProperties
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
// For each schemaId, sort property Attestations by timeCreated DESC
|
|
67
|
+
Object.keys(selectedPropertiesMap).forEach((schemaId) => {
|
|
68
|
+
const sorted = selectedPropertiesMap[schemaId].sort((a, b) => {
|
|
69
|
+
return a.timeCreated - b.timeCreated
|
|
70
|
+
})
|
|
71
|
+
selectedPropertiesMap[schemaId] = sorted
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
Object.keys(selectedPropertiesMap).forEach((schemaId) => {
|
|
75
|
+
// TODO: Finish this logic
|
|
76
|
+
// console.log('[singleItemActors] [fetchDataFromEas] schemaId', schemaId)
|
|
77
|
+
// sendBack({ type: 'addPropertyAttestation', schemaId })
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
// Attach processed properties to the itemService/itemMachine context
|
|
81
|
+
sendBack({
|
|
82
|
+
type: 'updatedPropertiesBySchemaUid',
|
|
83
|
+
propertiesBySchemaUid: selectedPropertiesMap,
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
_fetchDataFromEas().then(() => {
|
|
88
|
+
sendBack({ type: 'fetchDataFromEasSuccess' })
|
|
89
|
+
})
|
|
90
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EventObject, fromCallback } from 'xstate'
|
|
2
|
+
import { itemMachineAll } from '@/browser/item/all/itemMachineAll'
|
|
3
|
+
|
|
4
|
+
export const fetchDbData = fromCallback<EventObject, typeof itemMachineAll>(
|
|
5
|
+
({ sendBack, input: { context } }) => {
|
|
6
|
+
const { modelNamePlural, times } = context
|
|
7
|
+
|
|
8
|
+
const _fetchDbData = async (): Promise<void> => {}
|
|
9
|
+
|
|
10
|
+
_fetchDbData().then(() => {
|
|
11
|
+
sendBack({ type: 'fetchDbDataSuccess' })
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
return () => {}
|
|
15
|
+
},
|
|
16
|
+
)
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { EventObject, fromCallback } from 'xstate'
|
|
2
|
+
import {
|
|
3
|
+
GET_ALL_PROPERTIES_FOR_ALL_VERSIONS,
|
|
4
|
+
GET_SEED_IDS,
|
|
5
|
+
GET_VERSIONS,
|
|
6
|
+
} from '@/browser/item/queries'
|
|
7
|
+
import {
|
|
8
|
+
models as modelsTable,
|
|
9
|
+
modelUids,
|
|
10
|
+
PropertyType,
|
|
11
|
+
} from '@/shared/seedSchema'
|
|
12
|
+
import { Attestation } from '@/browser/gql/graphql'
|
|
13
|
+
import {
|
|
14
|
+
AllItemsMachineContext,
|
|
15
|
+
FromCallbackInput,
|
|
16
|
+
ModelClassType,
|
|
17
|
+
} from '@/types'
|
|
18
|
+
import { getAddressesFromDb } from '@/shared/helpers/db'
|
|
19
|
+
import { eq } from 'drizzle-orm'
|
|
20
|
+
import { easClient, queryClient } from '@/browser/helpers'
|
|
21
|
+
import { getAppDb } from '@/browser/db/sqlWasmClient'
|
|
22
|
+
|
|
23
|
+
export const fetchRelatedItems = fromCallback<
|
|
24
|
+
EventObject,
|
|
25
|
+
FromCallbackInput<AllItemsMachineContext>
|
|
26
|
+
>(({ sendBack, input: { context } }) => {
|
|
27
|
+
const { ModelClass, modelName } = context
|
|
28
|
+
|
|
29
|
+
const appDb = getAppDb()
|
|
30
|
+
|
|
31
|
+
const relatedProperties = new Map<string, PropertyType>()
|
|
32
|
+
const relatedVersionsBySeedUid = new Map<string, Attestation[]>()
|
|
33
|
+
const schemaUidsByModelName = new Map<string, string>()
|
|
34
|
+
const mostRecentVersionsBySeedUid = new Map<string, Attestation>()
|
|
35
|
+
const mostRecentPropertiesBySeedUid = new Map<string, Attestation[]>()
|
|
36
|
+
const seedUidsByMostRecentVersionUid = new Map<string, string>()
|
|
37
|
+
|
|
38
|
+
const _fetchRelatedItems = async () => {
|
|
39
|
+
// Get related properties
|
|
40
|
+
for (const [propertyName, propertyDef] of Object.entries(
|
|
41
|
+
(ModelClass as ModelClassType).schema,
|
|
42
|
+
)) {
|
|
43
|
+
if (propertyDef && propertyDef.ref && propertyDef.refModelId) {
|
|
44
|
+
relatedProperties.set(propertyName, propertyDef)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const addresses = await getAddressesFromDb(appDb)
|
|
49
|
+
|
|
50
|
+
// Get the models they point to from sdkConfigDb
|
|
51
|
+
for (const [propertyName, propertyDef] of relatedProperties.entries()) {
|
|
52
|
+
const relatedModelQuery = await appDb
|
|
53
|
+
.select({
|
|
54
|
+
id: modelsTable.id,
|
|
55
|
+
name: modelsTable.name,
|
|
56
|
+
uid: modelUids.uid,
|
|
57
|
+
})
|
|
58
|
+
.from(modelsTable)
|
|
59
|
+
.leftJoin(modelUids, eq(modelsTable.id, modelUids.modelId))
|
|
60
|
+
.where(eq(modelsTable.id, propertyDef.refModelId))
|
|
61
|
+
.limit(1)
|
|
62
|
+
|
|
63
|
+
if (relatedModelQuery && relatedModelQuery.length > 0) {
|
|
64
|
+
const relatedModel = relatedModelQuery[0]
|
|
65
|
+
const relatedModelUid = relatedModel.uid
|
|
66
|
+
// Exclude the current model's schemaUid since we already have its versions
|
|
67
|
+
if (relatedModelUid && relatedModelUid !== ModelClass.schemaUid) {
|
|
68
|
+
schemaUidsByModelName.set(relatedModel.name, relatedModelUid)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const queryKey = [`getRelatedSeedIds${modelName}`]
|
|
74
|
+
|
|
75
|
+
const { itemSeedIds: relatedSeedIdAttestations } =
|
|
76
|
+
await queryClient.fetchQuery({
|
|
77
|
+
queryKey,
|
|
78
|
+
queryFn: async () =>
|
|
79
|
+
easClient.request(GET_SEED_IDS, {
|
|
80
|
+
where: {
|
|
81
|
+
schema: {
|
|
82
|
+
is: {
|
|
83
|
+
id: {
|
|
84
|
+
in: Array.from(schemaUidsByModelName.values()),
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
attester: {
|
|
89
|
+
in: addresses,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
}),
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
const relatedSeedIds = relatedSeedIdAttestations.map((seed) => seed.id)
|
|
96
|
+
|
|
97
|
+
const { itemVersions: relatedVersions } = await queryClient.fetchQuery({
|
|
98
|
+
queryKey: [`getRelatedVersions${modelName}`],
|
|
99
|
+
queryFn: async () =>
|
|
100
|
+
easClient.request(GET_VERSIONS, {
|
|
101
|
+
where: {
|
|
102
|
+
refUID: {
|
|
103
|
+
in: relatedSeedIds,
|
|
104
|
+
},
|
|
105
|
+
attester: {
|
|
106
|
+
in: addresses,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
}),
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
// Index versions by seedUid
|
|
113
|
+
for (const version of relatedVersions) {
|
|
114
|
+
const existingVersionsForSeedUid =
|
|
115
|
+
relatedVersionsBySeedUid.get(version.refUID) || []
|
|
116
|
+
existingVersionsForSeedUid.push(version)
|
|
117
|
+
relatedVersionsBySeedUid.set(version.refUID, existingVersionsForSeedUid)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Sort the indexed versions by timeCreated and index the most recent
|
|
121
|
+
for (const [
|
|
122
|
+
seedUid,
|
|
123
|
+
versionsForSeed,
|
|
124
|
+
] of relatedVersionsBySeedUid.entries()) {
|
|
125
|
+
const versionsForSeedSorted = versionsForSeed.sort(
|
|
126
|
+
(a: Attestation, b: Attestation) => {
|
|
127
|
+
return a.timeCreated - b.timeCreated
|
|
128
|
+
},
|
|
129
|
+
)
|
|
130
|
+
relatedVersionsBySeedUid.set(seedUid, versionsForSeedSorted)
|
|
131
|
+
mostRecentVersionsBySeedUid.set(seedUid, versionsForSeedSorted[0])
|
|
132
|
+
seedUidsByMostRecentVersionUid.set(versionsForSeedSorted[0].id, seedUid)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Extract the ids of the most recent versions
|
|
136
|
+
const mostRecentVersionIds = Array.from(
|
|
137
|
+
mostRecentVersionsBySeedUid.values(),
|
|
138
|
+
).map((version) => version.id)
|
|
139
|
+
|
|
140
|
+
const { allProperties } = await queryClient.fetchQuery({
|
|
141
|
+
queryKey: [`getAllProperties${modelName}`],
|
|
142
|
+
queryFn: async () =>
|
|
143
|
+
easClient.request(GET_ALL_PROPERTIES_FOR_ALL_VERSIONS, {
|
|
144
|
+
where: {
|
|
145
|
+
refUID: {
|
|
146
|
+
in: mostRecentVersionIds,
|
|
147
|
+
},
|
|
148
|
+
attester: {
|
|
149
|
+
in: addresses,
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
}),
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
for (const propertyAttestation of allProperties) {
|
|
156
|
+
const seedUidForProperty = seedUidsByMostRecentVersionUid.get(
|
|
157
|
+
propertyAttestation.refUID,
|
|
158
|
+
)
|
|
159
|
+
const existingPropertiesForSeedUid =
|
|
160
|
+
mostRecentPropertiesBySeedUid.get(seedUidForProperty!) || []
|
|
161
|
+
existingPropertiesForSeedUid.push(propertyAttestation)
|
|
162
|
+
mostRecentPropertiesBySeedUid.set(
|
|
163
|
+
seedUidForProperty!,
|
|
164
|
+
existingPropertiesForSeedUid,
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
_fetchRelatedItems().then(() => {
|
|
170
|
+
sendBack({
|
|
171
|
+
type: 'fetchRelatedItemsSuccess',
|
|
172
|
+
mostRecentPropertiesBySeedUid,
|
|
173
|
+
relatedVersionsBySeedUid,
|
|
174
|
+
relatedProperties,
|
|
175
|
+
schemaUidsByModelName,
|
|
176
|
+
})
|
|
177
|
+
return
|
|
178
|
+
})
|
|
179
|
+
})
|