@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,150 @@
|
|
|
1
|
+
import { fs } from '@zenfs/core'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { Endpoints } from '@/types'
|
|
4
|
+
import { BROWSER_FS_TOP_DIR } from '@/browser/services/internal/constants'
|
|
5
|
+
import debug from 'debug'
|
|
6
|
+
|
|
7
|
+
const logger = debug('app:services:internal:helpers')
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Recursively create directories if they don't exist.
|
|
11
|
+
* @param {string} dirPath - The directory path to create.
|
|
12
|
+
*/
|
|
13
|
+
export const createDirectories = async (dirPath: string) => {
|
|
14
|
+
const dirPathExists = await fs.promises.exists(dirPath)
|
|
15
|
+
if (dirPathExists) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const parentDir = path.dirname(dirPath)
|
|
20
|
+
const parentDirExists = await fs.promises.exists(parentDir)
|
|
21
|
+
if (!parentDirExists) {
|
|
22
|
+
await createDirectories(parentDir)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
await fs.promises.mkdir(dirPath, { recursive: true })
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let busy = false
|
|
29
|
+
|
|
30
|
+
export const downloadFile = async (url: string, localFilePath: string) => {
|
|
31
|
+
try {
|
|
32
|
+
const response = await fetch(url)
|
|
33
|
+
const fileData = await response.text().catch((error) => {
|
|
34
|
+
console.error(`Failed to parse text from ${url}:`, error)
|
|
35
|
+
})
|
|
36
|
+
if (!fileData) {
|
|
37
|
+
console.error(`No file data from ${url}`)
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
const localDirPath = path.dirname(localFilePath)
|
|
41
|
+
|
|
42
|
+
if (busy) {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
busy = true
|
|
47
|
+
|
|
48
|
+
await createDirectories(localDirPath)
|
|
49
|
+
|
|
50
|
+
const filename = path.basename(localFilePath)
|
|
51
|
+
|
|
52
|
+
const regex = /(\d+)[\w_]+\.(sql|json)$/
|
|
53
|
+
|
|
54
|
+
const match = filename.match(regex)
|
|
55
|
+
|
|
56
|
+
let migrationNumber
|
|
57
|
+
|
|
58
|
+
if (match && match.length > 1) {
|
|
59
|
+
migrationNumber = match[1]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (migrationNumber) {
|
|
63
|
+
const filesInDir = await fs.promises.readdir(localDirPath)
|
|
64
|
+
for (const file of filesInDir) {
|
|
65
|
+
if (file === filename) {
|
|
66
|
+
continue
|
|
67
|
+
}
|
|
68
|
+
const innerMatch = file.match(regex)
|
|
69
|
+
let existingFileMigrationNumber
|
|
70
|
+
if (innerMatch && innerMatch.length > 1) {
|
|
71
|
+
existingFileMigrationNumber = innerMatch[1]
|
|
72
|
+
}
|
|
73
|
+
if (
|
|
74
|
+
migrationNumber &&
|
|
75
|
+
existingFileMigrationNumber &&
|
|
76
|
+
existingFileMigrationNumber === migrationNumber
|
|
77
|
+
) {
|
|
78
|
+
await fs.promises.unlink(path.join(localDirPath, file))
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// if (filename === '_journal.json') {
|
|
84
|
+
// const exists = await fs.promises.exists(localFilePath)
|
|
85
|
+
// if (exists) {
|
|
86
|
+
// await fs.promises.rm(localFilePath)
|
|
87
|
+
// }
|
|
88
|
+
// await fs.promises.writeFile(localFilePath, fileData)
|
|
89
|
+
// }
|
|
90
|
+
//
|
|
91
|
+
// if (filename !== '_journal.json') {
|
|
92
|
+
// await fs.promises.writeFile(localFilePath, fileData)
|
|
93
|
+
// }
|
|
94
|
+
await fs.promises.writeFile(localFilePath, fileData)
|
|
95
|
+
} catch (error) {
|
|
96
|
+
if (JSON.stringify(error).includes('File exists')) {
|
|
97
|
+
const fileData = await fs.promises.readFile(localFilePath, 'utf-8')
|
|
98
|
+
}
|
|
99
|
+
logger(`[Error] Failed to download file from ${url}:`, error)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
busy = false
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export const fetchDirectory = async (url: string) => {
|
|
106
|
+
const response = await fetch(url)
|
|
107
|
+
return response.json()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const fetchFilesRecursively = async (
|
|
111
|
+
url: string,
|
|
112
|
+
localPath: string,
|
|
113
|
+
fileList: string[],
|
|
114
|
+
) => {
|
|
115
|
+
try {
|
|
116
|
+
for (const file of fileList) {
|
|
117
|
+
const fileUrl = `${url}/${file}`
|
|
118
|
+
const fileLocalPath = path.join(localPath, file)
|
|
119
|
+
|
|
120
|
+
// logger(`[fetchFilesRecursively] fileUrl: ${fileUrl}`)
|
|
121
|
+
// logger(`[fetchFilesRecursively] fileLocalPath: ${fileLocalPath}`)
|
|
122
|
+
|
|
123
|
+
await downloadFile(fileUrl, fileLocalPath)
|
|
124
|
+
}
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error(`Failed to fetch files from ${url}:`, error)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export const confirmFilesExist = async (filePaths: string[]) => {
|
|
131
|
+
let everythingDownloaded = false
|
|
132
|
+
|
|
133
|
+
for (const filePath of filePaths) {
|
|
134
|
+
const fullPath = path.join(BROWSER_FS_TOP_DIR, filePath)
|
|
135
|
+
everythingDownloaded = await fs.promises.exists(fullPath)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (!everythingDownloaded) {
|
|
139
|
+
setTimeout(async () => {
|
|
140
|
+
await confirmFilesExist(filePaths)
|
|
141
|
+
}, 500)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export const syncDbFiles = async ({ filePaths, files }: Endpoints) => {
|
|
146
|
+
const fileList = await fetchDirectory(filePaths)
|
|
147
|
+
await fetchFilesRecursively(files, BROWSER_FS_TOP_DIR, fileList)
|
|
148
|
+
await confirmFilesExist(fileList)
|
|
149
|
+
logger('[syncDbFiles] Files synced!')
|
|
150
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { EventObject, fromCallback } from 'xstate'
|
|
2
|
+
import { waitForEvent } from '@/browser/events'
|
|
3
|
+
import {
|
|
4
|
+
FromCallbackInput,
|
|
5
|
+
HydrateExistingItemEvent,
|
|
6
|
+
ItemMachineContext,
|
|
7
|
+
} from '@/types'
|
|
8
|
+
|
|
9
|
+
export const hydrateExistingItem = fromCallback<
|
|
10
|
+
EventObject,
|
|
11
|
+
FromCallbackInput<ItemMachineContext<any>, HydrateExistingItemEvent>
|
|
12
|
+
>(({ sendBack, input: { event, context } }) => {
|
|
13
|
+
const { existingItem } = event!
|
|
14
|
+
const { seedUid, seedLocalId, ModelClass } = context
|
|
15
|
+
|
|
16
|
+
if (!ModelClass) {
|
|
17
|
+
throw new Error('ModelClass not found')
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const modelName = ModelClass.originalConstructor.name
|
|
21
|
+
|
|
22
|
+
const _checkForItemOnAllItemsService = async (): Promise<boolean> => {
|
|
23
|
+
if (!existingItem.seedLocalId && !existingItem.seedUid) {
|
|
24
|
+
console.warn(
|
|
25
|
+
'[singleItemActors] [hydrateExistingItem] No seedLocalId or seedUid found on existingItem',
|
|
26
|
+
)
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!seedUid && !seedLocalId) {
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const results = await waitForEvent({
|
|
35
|
+
req: {
|
|
36
|
+
eventLabel: 'item.request',
|
|
37
|
+
data: {
|
|
38
|
+
modelName,
|
|
39
|
+
seedUid,
|
|
40
|
+
seedLocalId,
|
|
41
|
+
source: 'hydrateExistingItem',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
res: {
|
|
45
|
+
eventLabel: `item.${modelName}.${seedLocalId}.response`,
|
|
46
|
+
},
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
return true
|
|
50
|
+
|
|
51
|
+
// return new Promise((resolve) => {
|
|
52
|
+
// const timeStart = Date.now()
|
|
53
|
+
//
|
|
54
|
+
// const interval = setInterval(() => {
|
|
55
|
+
// const timeElapsed = Date.now() - timeStart
|
|
56
|
+
// if (timeElapsed > 2000) {
|
|
57
|
+
// eventEmitter.emit('item.request', {
|
|
58
|
+
// modelName,
|
|
59
|
+
// versionUid,
|
|
60
|
+
// versionLocalId,
|
|
61
|
+
// source: 'hydrateExistingItem',
|
|
62
|
+
// })
|
|
63
|
+
// }
|
|
64
|
+
// if (timeElapsed > 30000) {
|
|
65
|
+
// clearInterval(interval)
|
|
66
|
+
// console.error(
|
|
67
|
+
// `[singleItemActors] [hydrateExistingItem] ${timeElapsed / 1000}s elapsed for ${modelName} ${versionLocalId}`,
|
|
68
|
+
// context,
|
|
69
|
+
// )
|
|
70
|
+
// eventEmitter.removeListener(
|
|
71
|
+
// `item.${modelName}.response`,
|
|
72
|
+
// handleItemRequestResponse,
|
|
73
|
+
// )
|
|
74
|
+
// resolve(false)
|
|
75
|
+
// }
|
|
76
|
+
// }, 500)
|
|
77
|
+
|
|
78
|
+
// const handleItemRequestResponse = (event) => {
|
|
79
|
+
// if (
|
|
80
|
+
// event.item &&
|
|
81
|
+
// ((event.item.versionLocalId &&
|
|
82
|
+
// event.item.versionLocalId === versionLocalId) ||
|
|
83
|
+
// (event.item.versionUid && event.item.versionUid === versionUid))
|
|
84
|
+
// ) {
|
|
85
|
+
// clearInterval(interval)
|
|
86
|
+
// eventEmitter.removeListener(
|
|
87
|
+
// `item.${modelName}.response`,
|
|
88
|
+
// handleItemRequestResponse,
|
|
89
|
+
// )
|
|
90
|
+
// resolve(true)
|
|
91
|
+
// }
|
|
92
|
+
// }
|
|
93
|
+
//
|
|
94
|
+
// eventEmitter.addListener(
|
|
95
|
+
// `item.${modelName}.response`,
|
|
96
|
+
// handleItemRequestResponse,
|
|
97
|
+
// )
|
|
98
|
+
//
|
|
99
|
+
// eventEmitter.emit('item.request', {
|
|
100
|
+
// modelName,
|
|
101
|
+
// versionUid,
|
|
102
|
+
// versionLocalId,
|
|
103
|
+
// source: 'hydrateExistingItem',
|
|
104
|
+
// })
|
|
105
|
+
// })
|
|
106
|
+
|
|
107
|
+
// if (existingItem.versionLocalId && !existingItem.versionLocalId) {
|
|
108
|
+
// console.log(
|
|
109
|
+
// `[singleItemActors] [hydrateExistingItem] versionLocalId: ${existingItem.versionLocalId} versionUid: ${existingItem.versionUid}`,
|
|
110
|
+
// )
|
|
111
|
+
//
|
|
112
|
+
// return true
|
|
113
|
+
// }
|
|
114
|
+
//
|
|
115
|
+
// console.log(
|
|
116
|
+
// `[singleItemActors] [hydrateExistingItem] versionLocalId: ${existingItem.versionLocalId} versionUid: ${existingItem.versionUid}`,
|
|
117
|
+
// )
|
|
118
|
+
// return true
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
_checkForItemOnAllItemsService().then((shouldContinue) => {
|
|
122
|
+
if (!shouldContinue) {
|
|
123
|
+
sendBack({ type: 'hydrateExistingItemFailure' })
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
// for (const [key, value] of Object.entries(existingItem)) {
|
|
127
|
+
// sendBack({
|
|
128
|
+
// type: 'updateValue',
|
|
129
|
+
// propertyName: key,
|
|
130
|
+
// propertyValue: value,
|
|
131
|
+
// source: 'db',
|
|
132
|
+
// })
|
|
133
|
+
// }
|
|
134
|
+
|
|
135
|
+
sendBack({ type: 'hydrateExistingItemSuccess' })
|
|
136
|
+
})
|
|
137
|
+
})
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { EventObject, fromCallback } from 'xstate'
|
|
2
|
+
import { propertyMachine } from '../propertyMachine'
|
|
3
|
+
import { and, eq, or, sql } from 'drizzle-orm'
|
|
4
|
+
import { escapeSqliteString } from '@/shared/helpers/db'
|
|
5
|
+
import debug from 'debug'
|
|
6
|
+
import { fs } from '@zenfs/core'
|
|
7
|
+
import { metadata } from 'src/shared/seedSchema'
|
|
8
|
+
import { getAppDb } from '@/browser/db/sqlWasmClient'
|
|
9
|
+
|
|
10
|
+
const logger = debug('app:property:actors:hydrateFromDb')
|
|
11
|
+
|
|
12
|
+
export const hydrateFromDb = fromCallback<EventObject, typeof propertyMachine>(
|
|
13
|
+
({ sendBack, input: { context } }) => {
|
|
14
|
+
const {
|
|
15
|
+
seedUid,
|
|
16
|
+
seedLocalId,
|
|
17
|
+
propertyName: propertyNameRaw,
|
|
18
|
+
propertyValue,
|
|
19
|
+
propertyRecordSchema,
|
|
20
|
+
itemModelName,
|
|
21
|
+
} = context
|
|
22
|
+
|
|
23
|
+
let propertyName = propertyNameRaw
|
|
24
|
+
|
|
25
|
+
if (
|
|
26
|
+
propertyRecordSchema &&
|
|
27
|
+
propertyRecordSchema.ref &&
|
|
28
|
+
propertyRecordSchema.dataType === 'Relation' &&
|
|
29
|
+
!propertyNameRaw.endsWith('Id')
|
|
30
|
+
) {
|
|
31
|
+
propertyName = propertyNameRaw + 'Id'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (
|
|
35
|
+
propertyRecordSchema &&
|
|
36
|
+
propertyRecordSchema.ref &&
|
|
37
|
+
propertyRecordSchema.dataType === 'List' &&
|
|
38
|
+
!propertyNameRaw.endsWith('Ids')
|
|
39
|
+
) {
|
|
40
|
+
propertyName = propertyNameRaw + 'Ids'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const _hydrateFromDb = async () => {
|
|
44
|
+
const db = getAppDb()
|
|
45
|
+
|
|
46
|
+
let hydrateQuery
|
|
47
|
+
let safeValue = propertyValue
|
|
48
|
+
let propertyValueQueryString = `property_value `
|
|
49
|
+
let propertyNameQueryString = `property_name = '${propertyName}'`
|
|
50
|
+
let propertyNameQuery = eq(metadata.propertyName, propertyName)
|
|
51
|
+
|
|
52
|
+
if (safeValue && typeof propertyValue === 'string') {
|
|
53
|
+
safeValue = escapeSqliteString(propertyValue)
|
|
54
|
+
propertyValueQueryString += `= '${safeValue}'`
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!safeValue) {
|
|
58
|
+
propertyValueQueryString += 'IS NULL'
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (typeof propertyValue === 'number') {
|
|
62
|
+
propertyValueQueryString += `= ${propertyValue}`
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (
|
|
66
|
+
propertyRecordSchema &&
|
|
67
|
+
propertyRecordSchema.ref &&
|
|
68
|
+
propertyRecordSchema.dataType === 'Relation'
|
|
69
|
+
) {
|
|
70
|
+
let missingPropertyNameVariant
|
|
71
|
+
if (propertyName.endsWith('Id')) {
|
|
72
|
+
missingPropertyNameVariant = propertyName.slice(0, -2)
|
|
73
|
+
}
|
|
74
|
+
if (!propertyName.endsWith('Id')) {
|
|
75
|
+
missingPropertyNameVariant = propertyName + 'Id'
|
|
76
|
+
}
|
|
77
|
+
propertyNameQueryString += ` OR property_name = '${missingPropertyNameVariant}'`
|
|
78
|
+
propertyNameQuery = or(
|
|
79
|
+
eq(metadata.propertyName, propertyName),
|
|
80
|
+
eq(metadata.propertyName, missingPropertyNameVariant),
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const selectFromStatement = db
|
|
85
|
+
.select({
|
|
86
|
+
localId: metadata.localId,
|
|
87
|
+
uid: metadata.uid,
|
|
88
|
+
propertyName: metadata.propertyName,
|
|
89
|
+
propertyValue: metadata.propertyValue,
|
|
90
|
+
seedLocalId: metadata.seedLocalId,
|
|
91
|
+
seedUid: metadata.seedUid,
|
|
92
|
+
schemaUid: metadata.schemaUid,
|
|
93
|
+
refResolvedValue: metadata.refResolvedValue,
|
|
94
|
+
refResolvedDisplayValue: metadata.refResolvedDisplayValue,
|
|
95
|
+
})
|
|
96
|
+
.from(metadata)
|
|
97
|
+
|
|
98
|
+
if (seedUid && !seedLocalId) {
|
|
99
|
+
hydrateQuery = selectFromStatement.where(
|
|
100
|
+
and(eq(metadata.seedUid, seedUid), propertyNameQuery),
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (seedUid && seedLocalId) {
|
|
105
|
+
hydrateQuery = selectFromStatement.where(
|
|
106
|
+
and(
|
|
107
|
+
eq(metadata.seedLocalId, seedLocalId),
|
|
108
|
+
eq(metadata.seedUid, seedUid),
|
|
109
|
+
propertyNameQuery,
|
|
110
|
+
),
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!seedUid && seedLocalId) {
|
|
115
|
+
hydrateQuery = selectFromStatement.where(
|
|
116
|
+
and(eq(metadata.seedLocalId, seedLocalId), propertyNameQuery),
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!hydrateQuery) {
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const rows = await hydrateQuery.orderBy(
|
|
125
|
+
sql.raw('COALESCE(attestation_created_at, created_at) DESC'),
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
if (!rows || !rows.length) {
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const firstRow = rows[0]
|
|
133
|
+
|
|
134
|
+
const {
|
|
135
|
+
localId,
|
|
136
|
+
uid,
|
|
137
|
+
propertyName: propertyNameFromDb,
|
|
138
|
+
propertyValue: propertyValueFromDb,
|
|
139
|
+
seedLocalId: seedLocalIdFromDb,
|
|
140
|
+
seedUid: seedUidFromDb,
|
|
141
|
+
schemaUid: schemaUidFromDb,
|
|
142
|
+
refResolvedValue,
|
|
143
|
+
refResolvedDisplayValue,
|
|
144
|
+
} = firstRow
|
|
145
|
+
|
|
146
|
+
if (propertyName && !propertyNameFromDb) {
|
|
147
|
+
logger(
|
|
148
|
+
`Property name from code is ${propertyName} but has not value in db ${propertyNameFromDb} for Property.${localId}`,
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (
|
|
153
|
+
propertyName &&
|
|
154
|
+
propertyNameFromDb &&
|
|
155
|
+
!propertyNameFromDb.includes(propertyName) &&
|
|
156
|
+
!propertyName.includes(propertyNameFromDb) &&
|
|
157
|
+
propertyNameFromDb !== propertyName
|
|
158
|
+
) {
|
|
159
|
+
logger(
|
|
160
|
+
`Property name from db ${propertyNameFromDb} does not match property name ${propertyName} for Property.${localId}`,
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (propertyValue && propertyValueFromDb !== propertyValue) {
|
|
165
|
+
logger(
|
|
166
|
+
`Property value from db ${propertyValueFromDb} does not match property value ${propertyValue} for Property.${localId}`,
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (seedLocalIdFromDb !== seedLocalId) {
|
|
171
|
+
logger(
|
|
172
|
+
`Seed local id from db ${seedLocalIdFromDb} does not match seed local id ${seedLocalId} for Property.${localId}`,
|
|
173
|
+
)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (seedUidFromDb !== seedUid) {
|
|
177
|
+
logger(
|
|
178
|
+
`Seed uid from db ${seedUidFromDb} does not match seed uid ${seedUid} for Property.${localId}`,
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
sendBack({
|
|
183
|
+
type: 'updateContext',
|
|
184
|
+
localId,
|
|
185
|
+
uid,
|
|
186
|
+
propertyValue: propertyValueFromDb,
|
|
187
|
+
seedLocalId: seedLocalIdFromDb,
|
|
188
|
+
seedUid: seedUidFromDb,
|
|
189
|
+
schemaUid: schemaUidFromDb,
|
|
190
|
+
resolveValue: refResolvedValue,
|
|
191
|
+
resolveDisplayValue: refResolvedDisplayValue,
|
|
192
|
+
renderValue: refResolvedDisplayValue,
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
if (propertyNameFromDb === 'storageTransactionId') {
|
|
196
|
+
const { Item } = await import(`@/browser/item`)
|
|
197
|
+
const item = await Item.find({
|
|
198
|
+
seedLocalId,
|
|
199
|
+
modelName: itemModelName,
|
|
200
|
+
})
|
|
201
|
+
if (item) {
|
|
202
|
+
for (const [propertyName, property] of Object.entries(
|
|
203
|
+
item.properties,
|
|
204
|
+
)) {
|
|
205
|
+
if (
|
|
206
|
+
propertyName === 'html' &&
|
|
207
|
+
propertyValueFromDb &&
|
|
208
|
+
propertyValueFromDb.length === 43
|
|
209
|
+
) {
|
|
210
|
+
const htmlFilePath = `/files/html/${propertyValueFromDb}.html`
|
|
211
|
+
const exists = await fs.promises.exists(htmlFilePath)
|
|
212
|
+
if (!exists) {
|
|
213
|
+
return
|
|
214
|
+
}
|
|
215
|
+
const renderValue = await fs.promises
|
|
216
|
+
.readFile(htmlFilePath, 'utf8')
|
|
217
|
+
.catch((error) => {
|
|
218
|
+
logger('Error reading html file', error)
|
|
219
|
+
})
|
|
220
|
+
property
|
|
221
|
+
.getService()
|
|
222
|
+
.send({ type: 'updateRenderValue', renderValue })
|
|
223
|
+
return
|
|
224
|
+
}
|
|
225
|
+
if (
|
|
226
|
+
propertyName === 'json' &&
|
|
227
|
+
propertyValueFromDb &&
|
|
228
|
+
propertyValueFromDb.length === 43
|
|
229
|
+
) {
|
|
230
|
+
const jsonFilePath = `/files/json/${propertyValueFromDb}.json`
|
|
231
|
+
const exists = await fs.promises.exists(jsonFilePath)
|
|
232
|
+
if (!exists) {
|
|
233
|
+
return
|
|
234
|
+
}
|
|
235
|
+
const renderValue = await fs.promises
|
|
236
|
+
.readFile(jsonFilePath, 'utf8')
|
|
237
|
+
.catch((error) => {
|
|
238
|
+
logger('Error reading json file', error)
|
|
239
|
+
})
|
|
240
|
+
property
|
|
241
|
+
.getService()
|
|
242
|
+
.send({ type: 'updateRenderValue', renderValue })
|
|
243
|
+
return
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
_hydrateFromDb().then(() => {
|
|
251
|
+
sendBack({ type: 'hydrateFromDbSuccess' })
|
|
252
|
+
})
|
|
253
|
+
},
|
|
254
|
+
)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { EventObject, fromCallback } from 'xstate'
|
|
2
|
+
import { createSeed } from '@/browser/db/write'
|
|
3
|
+
import { FromCallbackInput, ItemMachineContext } from '@/types'
|
|
4
|
+
import { createVersion } from '@/browser/db/write/createVersion'
|
|
5
|
+
|
|
6
|
+
export const hydrateNewItem = fromCallback<
|
|
7
|
+
EventObject,
|
|
8
|
+
FromCallbackInput<ItemMachineContext<any>>
|
|
9
|
+
>(({ sendBack, input: { context } }) => {
|
|
10
|
+
const { seedUid, versionUid, modelName } = context
|
|
11
|
+
|
|
12
|
+
let newSeedLocalId: string
|
|
13
|
+
|
|
14
|
+
const _hydrateNewItem = async (): Promise<void> => {
|
|
15
|
+
if (!modelName) {
|
|
16
|
+
throw new Error('modelName is required')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
newSeedLocalId = await createSeed({
|
|
20
|
+
type: modelName.toLowerCase(),
|
|
21
|
+
seedUid: seedUid ?? 'NULL',
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
await createVersion({
|
|
25
|
+
seedLocalId: newSeedLocalId,
|
|
26
|
+
seedType: modelName.toLowerCase(),
|
|
27
|
+
uid: versionUid ?? 'NULL',
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_hydrateNewItem().then(() => {
|
|
32
|
+
sendBack({ type: 'hydrateNewItemSuccess' })
|
|
33
|
+
})
|
|
34
|
+
})
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { assign, setup } from 'xstate'
|
|
2
|
+
import {
|
|
3
|
+
fetchAllBinaryData,
|
|
4
|
+
fetchAllMetadataRecords,
|
|
5
|
+
} from '@/browser/schema/file/fetchAll/actors'
|
|
6
|
+
import { Attestation } from '@/browser/gql/graphql'
|
|
7
|
+
|
|
8
|
+
type FetchAllFilesMachineContext = {
|
|
9
|
+
addresses: string[]
|
|
10
|
+
dbsLoaded: boolean
|
|
11
|
+
filesMetadata?: Attestation[]
|
|
12
|
+
filesBlobData?: any[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const fetchAllFilesMachine = setup({
|
|
16
|
+
types: {
|
|
17
|
+
context: {} as FetchAllFilesMachineContext,
|
|
18
|
+
},
|
|
19
|
+
actors: {
|
|
20
|
+
fetchAllMetadataRecords,
|
|
21
|
+
fetchAllBinaryData,
|
|
22
|
+
},
|
|
23
|
+
}).createMachine({
|
|
24
|
+
id: 'fetchAllFiles',
|
|
25
|
+
initial: 'idle',
|
|
26
|
+
context: ({ input }) =>
|
|
27
|
+
({
|
|
28
|
+
...input,
|
|
29
|
+
dbsLoaded: false,
|
|
30
|
+
}) as FetchAllFilesMachineContext,
|
|
31
|
+
on: {
|
|
32
|
+
allDbsLoaded: {
|
|
33
|
+
target: '.fetchingAllMetadataRecords',
|
|
34
|
+
actions: assign({
|
|
35
|
+
dbsLoaded: true,
|
|
36
|
+
}),
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
states: {
|
|
40
|
+
idle: {},
|
|
41
|
+
fetchingAllMetadataRecords: {
|
|
42
|
+
on: {
|
|
43
|
+
fetchingAllMetadataRecordsSuccess: {
|
|
44
|
+
target: 'fetchingAllBinaryData',
|
|
45
|
+
actions: assign({
|
|
46
|
+
filesMetadata: ({ event }) => event.filesMetadata,
|
|
47
|
+
}),
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
invoke: {
|
|
51
|
+
src: 'fetchAllMetadataRecords',
|
|
52
|
+
input: ({ context, event }) => ({ context, event }),
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
fetchingAllBinaryData: {
|
|
56
|
+
on: {
|
|
57
|
+
fetchingAllBinaryDataSuccess: {
|
|
58
|
+
target: 'success',
|
|
59
|
+
actions: assign({
|
|
60
|
+
filesBlobData: ({ event }) => event.filesBlobData,
|
|
61
|
+
}),
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
invoke: {
|
|
65
|
+
src: 'fetchAllBinaryData',
|
|
66
|
+
input: ({ context }) => ({ context }),
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
success: {
|
|
70
|
+
type: 'final',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
})
|