@seedprotocol/sdk 0.1.46 → 0.1.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/dist/bin.js.map +1 -1
  2. package/dist/constants-BLctWkrn.js.map +1 -1
  3. package/dist/{index-BEzB8REh.js → index-DMIKRod-.js} +3684 -3660
  4. package/dist/index-DMIKRod-.js.map +1 -0
  5. package/dist/{index-ChGsdGPJ.js → index-wKss7188.js} +10 -10
  6. package/dist/index-wKss7188.js.map +1 -0
  7. package/dist/main.js +7 -7
  8. package/dist/{seed.schema.config-jKpK-lR6.js → seed.schema.config-C0M8Rcti.js} +7 -7
  9. package/dist/seed.schema.config-C0M8Rcti.js.map +1 -0
  10. package/dist/src/AppStateSchema.ts +10 -0
  11. package/dist/src/Attestation.ts +21 -0
  12. package/dist/src/ConfigSchema.ts +15 -0
  13. package/dist/src/ItemProperty.ts +383 -0
  14. package/dist/src/MetadataSchema.ts +28 -0
  15. package/dist/src/ModelSchema.ts +46 -0
  16. package/dist/src/ModelUidSchema.ts +16 -0
  17. package/dist/src/PropertyUidSchema.ts +16 -0
  18. package/dist/src/Schema.ts +17 -0
  19. package/dist/src/SeedSchema.ts +29 -0
  20. package/dist/src/VersionSchema.ts +16 -0
  21. package/dist/src/actors.ts +10 -0
  22. package/dist/src/addModelsToDb.ts +150 -0
  23. package/dist/src/allItems.ts +23 -0
  24. package/dist/src/arweave.ts +37 -0
  25. package/dist/src/browser.app.db.config.ts +27 -0
  26. package/dist/src/browser.seed.db.config.ts +33 -0
  27. package/dist/src/browser.ts +30 -0
  28. package/dist/src/checkStatus.ts +50 -0
  29. package/dist/src/client.ts +85 -0
  30. package/dist/src/configureFs.ts +81 -0
  31. package/dist/src/connectToDb.ts +74 -0
  32. package/dist/src/connectionManager.ts +67 -0
  33. package/dist/src/constants.ts +118 -0
  34. package/dist/src/create.ts +39 -0
  35. package/dist/src/createItem.ts +15 -0
  36. package/dist/src/createItemMachine.ts +37 -0
  37. package/dist/src/createPublishAttempt.ts +16 -0
  38. package/dist/src/createSeeds.ts +24 -0
  39. package/dist/src/createVersion.ts +33 -0
  40. package/dist/src/db.ts +247 -0
  41. package/dist/src/dbMachine.ts +181 -0
  42. package/dist/src/deleteItem.ts +19 -0
  43. package/dist/src/download.ts +289 -0
  44. package/dist/src/drizzle.ts +82 -0
  45. package/dist/src/environment.ts +15 -0
  46. package/dist/src/eventBus.ts +5 -0
  47. package/dist/src/events.ts +14 -0
  48. package/dist/src/fetchDataFromEas.ts +90 -0
  49. package/dist/src/fetchDbData.ts +16 -0
  50. package/dist/src/fetchRelatedItems.ts +179 -0
  51. package/dist/src/fetchSeeds.ts +44 -0
  52. package/dist/src/fetchVersions.ts +41 -0
  53. package/dist/src/files.ts +16 -0
  54. package/dist/src/fragment-masking.ts +87 -0
  55. package/dist/src/fsProxy.ts +36 -0
  56. package/dist/src/getItem.ts +189 -0
  57. package/dist/src/getItemProperties.ts +162 -0
  58. package/dist/src/getItems.ts +75 -0
  59. package/dist/src/getMetadata.ts +40 -0
  60. package/dist/src/getModelSchemas.ts +88 -0
  61. package/dist/src/getSchemaForModel.ts +42 -0
  62. package/dist/src/getSeedData.ts +34 -0
  63. package/dist/src/getVersionData.ts +58 -0
  64. package/dist/src/getVersionsForVersionUids.ts +39 -0
  65. package/dist/src/globalMachine.ts +259 -0
  66. package/dist/src/gql.ts +113 -0
  67. package/dist/src/graphql.ts +3201 -0
  68. package/dist/src/helpers.ts +150 -0
  69. package/dist/src/hydrateExistingItem.ts +137 -0
  70. package/dist/src/hydrateFromDb.ts +254 -0
  71. package/dist/src/hydrateNewItem.ts +34 -0
  72. package/dist/src/index.d.ts +5 -0
  73. package/dist/src/index.ts +21 -0
  74. package/dist/src/init.ts +61 -0
  75. package/dist/src/initialize.ts +127 -0
  76. package/dist/src/internalMachine.ts +220 -0
  77. package/dist/src/item.ts +324 -0
  78. package/dist/src/itemMachineAll.ts +158 -0
  79. package/dist/src/itemMachineSingle.ts +175 -0
  80. package/dist/src/loadAppDb.ts +47 -0
  81. package/dist/src/logger.ts +33 -0
  82. package/dist/src/machine.ts +55 -0
  83. package/dist/src/machines.ts +58 -0
  84. package/dist/src/migrate.ts +288 -0
  85. package/dist/src/model.ts +71 -0
  86. package/dist/src/modelClass.ts +19 -0
  87. package/dist/src/node.app.db.config.ts +40 -0
  88. package/dist/src/prepareDb.ts +34 -0
  89. package/dist/src/preparePublishRequestData.ts +81 -0
  90. package/dist/src/processItems.ts +71 -0
  91. package/dist/src/property.ts +161 -0
  92. package/dist/src/propertyMachine.ts +154 -0
  93. package/dist/src/publish.ts +31 -0
  94. package/dist/src/publishMachine.ts +77 -0
  95. package/dist/src/queries.ts +13 -0
  96. package/dist/src/read.ts +174 -0
  97. package/dist/src/recoverDeletedItem.ts +14 -0
  98. package/dist/src/request.ts +54 -0
  99. package/dist/src/requestAll.ts +157 -0
  100. package/dist/src/resolveRelatedValue.ts +348 -0
  101. package/dist/src/resolveRemoteStorage.ts +87 -0
  102. package/dist/src/save.ts +183 -0
  103. package/dist/src/saveConfig.ts +79 -0
  104. package/dist/src/saveDataToDb.ts +145 -0
  105. package/dist/src/saveMetadata.ts +18 -0
  106. package/dist/src/saveValueToDb.ts +94 -0
  107. package/dist/src/seed.schema.config.ts +25 -0
  108. package/dist/src/seed.ts +37 -0
  109. package/dist/src/seedData.ts +0 -0
  110. package/dist/src/seedProtocol.ts +17 -0
  111. package/dist/src/services.ts +359 -0
  112. package/dist/src/sqlWasmClient.ts +88 -0
  113. package/dist/src/syncDbWithEas.ts +686 -0
  114. package/dist/src/trash.ts +29 -0
  115. package/dist/src/ts-to-proto.ts +101 -0
  116. package/dist/src/types.ts +12 -0
  117. package/dist/src/upload.ts +86 -0
  118. package/dist/src/validate.ts +42 -0
  119. package/dist/src/validateInput.ts +33 -0
  120. package/dist/src/validateItemData.ts +20 -0
  121. package/dist/src/waitForDb.ts +23 -0
  122. package/dist/src/wasm.d.ts +8300 -0
  123. package/dist/src/write.ts +366 -0
  124. package/dist/types/src/browser/db/read/getModelSchemas.d.ts.map +1 -1
  125. package/dist/types/src/browser/events/item/create.d.ts.map +1 -1
  126. package/dist/types/src/browser/events/item/publish.d.ts.map +1 -1
  127. package/dist/types/src/browser/events/item/requestAll.d.ts.map +1 -1
  128. package/dist/types/src/browser/events/item/syncDbWithEas.d.ts.map +1 -1
  129. package/dist/types/src/browser/item/single/actors/hydrateExistingItem.d.ts +3 -1
  130. package/dist/types/src/browser/item/single/actors/hydrateExistingItem.d.ts.map +1 -1
  131. package/dist/types/src/browser/item/single/actors/saveDataToDb.d.ts +3 -3
  132. package/dist/types/src/browser/item/single/itemMachineSingle.d.ts +3 -3
  133. package/dist/types/src/browser/property/ItemProperty.d.ts +7 -7
  134. package/dist/types/src/browser/property/ItemProperty.d.ts.map +1 -1
  135. package/dist/types/src/browser/property/actors/hydrateFromDb.d.ts.map +1 -1
  136. package/dist/types/src/browser/property/actors/initialize.d.ts.map +1 -1
  137. package/dist/types/src/browser/property/actors/resolveRemoteStorage.d.ts +3 -3
  138. package/dist/types/src/browser/react/trash.d.ts +1 -1
  139. package/dist/types/src/browser/react/trash.d.ts.map +1 -1
  140. package/dist/types/src/browser/services/db/dbMachine.d.ts +6 -6
  141. package/dist/types/src/browser/services/publish/publishMachine.d.ts +17 -17
  142. package/dist/types/src/types/machines.d.ts +4 -0
  143. package/dist/types/src/types/machines.d.ts.map +1 -1
  144. package/package.json +1 -1
  145. package/dist/index-BEzB8REh.js.map +0 -1
  146. package/dist/index-ChGsdGPJ.js.map +0 -1
  147. package/dist/seed.schema.config-jKpK-lR6.js.map +0 -1
@@ -0,0 +1,67 @@
1
+ type SqliteDatabase = {
2
+ open: (filename: string) => Promise<void>
3
+ exec: (sql: string, params?: any[]) => any
4
+ close: () => void
5
+ }
6
+
7
+ class SqliteConnectionManager {
8
+ private sqliteModule: SqliteDatabase
9
+ private idleTimeout: number
10
+ private databases: { [key: string]: SqliteDatabase }
11
+ private idleTimers: { [key: string]: NodeJS.Timeout }
12
+
13
+ constructor(sqliteModule: SqliteDatabase, idleTimeout: number = 300000) {
14
+ // Default idle timeout: 5 minutes
15
+ this.sqliteModule = sqliteModule
16
+ this.idleTimeout = idleTimeout
17
+ this.databases = {}
18
+ this.idleTimers = {}
19
+ }
20
+
21
+ private resetIdleTimer(dbName: string): void {
22
+ if (this.idleTimers[dbName]) {
23
+ clearTimeout(this.idleTimers[dbName])
24
+ }
25
+
26
+ this.idleTimers[dbName] = setTimeout(() => {
27
+ this.closeConnection(dbName)
28
+ }, this.idleTimeout)
29
+ }
30
+
31
+ private async getConnection(dbName: string): Promise<SqliteDatabase> {
32
+ if (this.databases[dbName]) {
33
+ this.resetIdleTimer(dbName)
34
+ return this.databases[dbName]
35
+ }
36
+
37
+ const db = new this.sqliteModule()
38
+ await db.open(dbName)
39
+ this.databases[dbName] = db
40
+ this.resetIdleTimer(dbName)
41
+ return db
42
+ }
43
+
44
+ public async execute(
45
+ dbName: string,
46
+ sql: string,
47
+ params: any[] = [],
48
+ ): Promise<any> {
49
+ const db = await this.getConnection(dbName)
50
+ const result = db.exec(sql, params)
51
+ this.resetIdleTimer(dbName)
52
+ return result
53
+ }
54
+
55
+ public closeConnection(dbName: string): void {
56
+ if (this.databases[dbName]) {
57
+ this.databases[dbName].close()
58
+ delete this.databases[dbName]
59
+ if (this.idleTimers[dbName]) {
60
+ clearTimeout(this.idleTimers[dbName])
61
+ delete this.idleTimers[dbName]
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ export { SqliteConnectionManager }
@@ -0,0 +1,118 @@
1
+ const MACHINE_ID_SCOPE = '@seedSdk'
2
+
3
+ export enum MachineIds {
4
+ GLOBAL = `${MACHINE_ID_SCOPE}/global`,
5
+ INTERNAL = `${MACHINE_ID_SCOPE}/internal`,
6
+ DB = `${MACHINE_ID_SCOPE}/db`,
7
+ EAS = `${MACHINE_ID_SCOPE}/eas`,
8
+ ITEM = `${MACHINE_ID_SCOPE}/item`,
9
+ ALL_ITEMS = `${MACHINE_ID_SCOPE}/allItems`,
10
+ MODEL = `${MACHINE_ID_SCOPE}/model`,
11
+ FILE_SYSTEM = `${MACHINE_ID_SCOPE}/fileSystem`,
12
+ }
13
+
14
+ const { INTERNAL, DB, GLOBAL, EAS, MODEL } = MachineIds
15
+
16
+ export enum GlobalState {
17
+ UNINITIALIZED = 'uninitialized',
18
+ INITIALIZING = 'initializing',
19
+ INITIALIZED = 'initialized',
20
+ PUBLISHING_ITEM = 'publishingItem',
21
+ ADDING_MODELS_TO_DB = 'addingModelsToDb',
22
+ }
23
+
24
+ const {
25
+ UNINITIALIZED,
26
+ INITIALIZING,
27
+ INITIALIZED,
28
+ PUBLISHING_ITEM,
29
+ ADDING_MODELS_TO_DB,
30
+ } = GlobalState
31
+
32
+ export enum InternalState {
33
+ IDLE = 'idle',
34
+ INITIALIZING = 'initializing',
35
+ VALIDATING_INPUT = 'validatingInput',
36
+ CONFIGURING_FS = 'configuringFs',
37
+ LOADING_SEED_DB = 'loadingSeedDb',
38
+ SAVING_CONFIG = 'savingConfig',
39
+ LOADING_APP_DB = 'loadingAppDb',
40
+ LOADING_SDK_DB = 'loadingSdkDb',
41
+ }
42
+
43
+ const { VALIDATING_INPUT, CONFIGURING_FS, LOADING_SEED_DB, LOADING_APP_DB } =
44
+ InternalState
45
+
46
+ export enum DbState {
47
+ CHECKING_STATUS = 'checkingStatus',
48
+ WAITING_FOR_FILES = 'waitingForFiles',
49
+ VALIDATING = 'validating',
50
+ CONNECTING_TO_DB = 'connectingToDb',
51
+ // FETCHING_MIGRATIONS = 'fetchingMigrations',
52
+ MIGRATING = 'migrating',
53
+ }
54
+
55
+ const {
56
+ CHECKING_STATUS,
57
+ VALIDATING,
58
+ CONNECTING_TO_DB,
59
+ WAITING_FOR_FILES,
60
+ MIGRATING,
61
+ } = DbState
62
+
63
+ export enum PublishMachineStates {
64
+ VALIDATING_ITEM_DATA = 'validatingItemData',
65
+ CREATING_PUBLISH_ATTEMPT = 'creatingPublishAttempt',
66
+ UPLOADING = 'uploading',
67
+ PREPARING_PUBLISH_REQUEST_DATA = 'preparingPublishRequestData',
68
+ PUBLISHING = 'publishing',
69
+ IDLE = 'idle',
70
+ }
71
+
72
+ export const INTERNAL_VALIDATING_INPUT_SUCCESS = `${INTERNAL}.${VALIDATING_INPUT}.success`
73
+
74
+ export const INTERNAL_CONFIGURING_FS_SUCCESS = `${INTERNAL}.${CONFIGURING_FS}.success`
75
+ export const INTERNAL_CONFIGURING_FS_FAILURE = `${INTERNAL}.${CONFIGURING_FS}.failure`
76
+
77
+ export const INTERNAL_LOADING_SEED_DB_SUCCESS = `${INTERNAL}.${LOADING_SEED_DB}.success`
78
+ export const INTERNAL_LOADING_SEED_DB_FAILURE = `${INTERNAL}.${LOADING_SEED_DB}.failure`
79
+
80
+ export const INTERNAL_LOADING_APP_DB_SUCCESS = `${INTERNAL}.${LOADING_APP_DB}.success`
81
+ export const INTERNAL_LOADING_APP_DB_FAILURE = `${INTERNAL}.${LOADING_APP_DB}.failure`
82
+
83
+ export const INTERNAL_SAVING_CONFIG_SUCCESS = `${INTERNAL}.savingConfig.success`
84
+ export const INTERNAL_SAVING_CONFIG_FAILURE = `${INTERNAL}.savingConfig.failure`
85
+
86
+ export const GLOBAL_GETTING_SEED_CLASS_SUCCESS = `${GLOBAL}.${PUBLISHING_ITEM}.success`
87
+ export const GLOBAL_INITIALIZING_SEND_CONFIG = `${GLOBAL}.${INITIALIZING}.sendConfig`
88
+ export const GLOBAL_INITIALIZING_INTERNAL_SERVICE_READY = `${GLOBAL}.${INITIALIZING}.internalServiceReady`
89
+ export const GLOBAL_INITIALIZING_CREATE_ALL_ITEMS_SERVICES = `${GLOBAL}.${INITIALIZING}.createAllItemsServices`
90
+ export const GLOBAL_ADDING_MODELS_TO_DB_SUCCESS = `${GLOBAL}.${ADDING_MODELS_TO_DB}.success`
91
+
92
+ export const DB_CHECK_STATUS_UPDATE_PATHS = `${DB}.${CHECKING_STATUS}.updatePaths`
93
+ export const DB_CHECK_STATUS_EXISTS = `${DB}.${CHECKING_STATUS}.exists`
94
+ export const DB_CHECK_STATUS_DOES_NOT_EXIST = `${DB}.${CHECKING_STATUS}.doesNotExist`
95
+ export const DB_CHECK_STATUS_FAILURE = `${DB}.${CHECKING_STATUS}.failure`
96
+
97
+ export const DB_VALIDATING_SUCCESS = `${DB}.${VALIDATING}.success`
98
+ export const DB_VALIDATING_WAIT = `${DB}.${VALIDATING}.wait`
99
+ export const DB_MIGRATING_WAIT = `${DB}.${MIGRATING}.wait`
100
+ export const DB_MIGRATING_SUCCESS = `${DB}.${MIGRATING}.success`
101
+ export const DB_CREATING_SUCCESS = `${DB}.${CONNECTING_TO_DB}.success`
102
+ export const DB_WAITING_FOR_FILES_RECEIVED = `${DB}.${WAITING_FOR_FILES}.filesReceived`
103
+ export const DB_ON_SNAPSHOT = `${DB}.onSnapshot`
104
+ export const CHILD_SNAPSHOT = 'childSnapshot'
105
+
106
+ export const INTERNAL_SERVICE_SNAPSHOT = 'internalServiceSnapshot'
107
+
108
+ export const DB_NAME_APP = 'app_db'
109
+ export const BROWSER_FS_TOP_DIR = 'app-files'
110
+
111
+ export const EAS_ENDPOINT =
112
+ process.env.NEXT_PUBLIC_EAS_ENDPOINT ||
113
+ process.env.EAS_ENDPOINT ||
114
+ 'https://optimism-sepolia.easscan.org/graphql'
115
+
116
+ export const ARWEAVE_HOST =
117
+ process.env.NEXT_PUBLIC_ARWEAVE_HOST || 'permagate.io'
118
+ export const ARWEAVE_ENDPOINT = `https://${ARWEAVE_HOST}/graphql`
@@ -0,0 +1,39 @@
1
+ import { Item } from 'src/browser/item'
2
+ import { eventEmitter } from '@/eventBus'
3
+ import { createItemCacheKey, getItemCache, updateItemCache } from './requestAll'
4
+
5
+ export const createItemRequestHandler = async (event) => {
6
+ const { ModelClass, itemData } = event
7
+
8
+ const itemCache = getItemCache()
9
+
10
+ const itemCacheKey = createItemCacheKey(itemData)
11
+
12
+ if (!itemCacheKey) {
13
+ console.warn('itemCacheKey not found for itemData', itemData)
14
+ return
15
+ }
16
+
17
+ if (itemCache.has(itemCacheKey)) {
18
+ return
19
+ }
20
+
21
+ const newItem = Item.create({
22
+ modelName: ModelClass.originalConstructor.name,
23
+ ...itemData,
24
+ })
25
+
26
+ updateItemCache(itemCacheKey, newItem)
27
+
28
+ return new Promise<void>((resolve) => {
29
+ const subscription = newItem.subscribe((context) => {
30
+ if (context && context.versionLocalId && context.seedLocalId) {
31
+ subscription.unsubscribe()
32
+ // allItemsService.send({ type: 'addItemToContext', item: newItem })
33
+ eventEmitter.emit('item.create.response', { item: newItem })
34
+ // eventEmitter.emit('item.requestAll', { modelName })
35
+ resolve()
36
+ }
37
+ })
38
+ })
39
+ }
@@ -0,0 +1,15 @@
1
+ import { EventObject, fromCallback } from 'xstate'
2
+ import { createItemMachine } from '../createItemMachine'
3
+
4
+ export const createItem = fromCallback<EventObject, typeof createItemMachine>(
5
+ ({ sendBack, input: { context, event } }) => {
6
+ const { item } = context
7
+
8
+ if (!item) {
9
+ console.warn('No item found')
10
+ return
11
+ }
12
+
13
+ sendBack({ type: 'itemCreated', item })
14
+ },
15
+ )
@@ -0,0 +1,37 @@
1
+ import { setup } from 'xstate'
2
+
3
+ const createItemMachine = setup({
4
+ types: {
5
+ context: {},
6
+ input: {},
7
+ },
8
+ }).createMachine({
9
+ id: 'createItem',
10
+ initial: 'creating',
11
+ context: ({ input }) => input as any,
12
+ states: {
13
+ idle: {
14
+ on: {
15
+ create: 'creating',
16
+ },
17
+ },
18
+ creating: {
19
+ invoke: {
20
+ src: 'createItem',
21
+ onDone: {
22
+ target: 'created',
23
+ actions: 'onSuccess',
24
+ },
25
+ onError: {
26
+ target: 'idle',
27
+ actions: 'onError',
28
+ },
29
+ },
30
+ },
31
+ created: {
32
+ type: 'final',
33
+ },
34
+ },
35
+ })
36
+
37
+ export { createItemMachine }
@@ -0,0 +1,16 @@
1
+ import { EventObject, fromCallback } from 'xstate'
2
+ import { FromCallbackInput, PublishMachineContext } from '@/types'
3
+
4
+ export const createPublishAttempt = fromCallback<
5
+ EventObject,
6
+ FromCallbackInput<PublishMachineContext>
7
+ >(({ sendBack, input: { context } }) => {
8
+ const _createPublishAttempt = async () => {
9
+ // Do some stuff
10
+ return true
11
+ }
12
+
13
+ _createPublishAttempt().then(() => {
14
+ sendBack({ type: 'createPublishAttemptSuccess' })
15
+ })
16
+ })
@@ -0,0 +1,24 @@
1
+ import { seeds, SeedType } from '@/shared/seedSchema'
2
+ import { getAppDb } from '@/browser/db/sqlWasmClient'
3
+
4
+ type CreateSeeds = (newSeeds: Partial<SeedType>[]) => Promise<string[]>
5
+
6
+ export const createSeeds: CreateSeeds = async (
7
+ newSeeds: Partial<SeedType>[],
8
+ ) => {
9
+ const appDb = getAppDb()
10
+
11
+ const results = await appDb
12
+ .insert(seeds)
13
+ .values(newSeeds)
14
+ .returning({ uid: seeds.uid })
15
+
16
+ const newUids = results.reduce((acc, result) => {
17
+ if (result.uid) {
18
+ acc.push(result.uid)
19
+ }
20
+ return acc
21
+ }, [] as string[])
22
+
23
+ return newUids
24
+ }
@@ -0,0 +1,33 @@
1
+ import { getAppDb } from '../sqlWasmClient'
2
+ import { generateId } from '@/shared/helpers'
3
+ import { versions } from '@/shared/seedSchema'
4
+
5
+ type CreateVersionProps = {
6
+ seedLocalId?: string
7
+ seedUid?: string
8
+ seedType?: string
9
+ uid?: string
10
+ }
11
+ type CreateVersion = (props: CreateVersionProps) => Promise<string>
12
+
13
+ export const createVersion: CreateVersion = async ({
14
+ seedLocalId,
15
+ seedUid,
16
+ seedType,
17
+ uid,
18
+ }) => {
19
+ const appDb = getAppDb()
20
+
21
+ const newVersionLocalId = generateId()
22
+
23
+ await appDb.insert(versions).values({
24
+ localId: newVersionLocalId,
25
+ createdAt: Date.now(),
26
+ seedLocalId,
27
+ seedUid: seedUid ?? 'NULL',
28
+ seedType,
29
+ uid: uid || 'NULL',
30
+ })
31
+
32
+ return newVersionLocalId
33
+ }
package/dist/src/db.ts ADDED
@@ -0,0 +1,247 @@
1
+ import {
2
+ appState,
3
+ models as modelsTable,
4
+ NewModelRecord,
5
+ NewPropertyRecord,
6
+ properties,
7
+ } from 'src/shared/seedSchema'
8
+ import { SqliteRemoteDatabase } from 'drizzle-orm/sqlite-proxy'
9
+ import { DbQueryResult, ModelDefinitions, ResultObject } from '@/types'
10
+ import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3'
11
+ import { SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core'
12
+ import { and, eq, isNull, SQL } from 'drizzle-orm'
13
+
14
+ import { getAppDb } from '@/browser/db/sqlWasmClient'
15
+
16
+ export const escapeSqliteString = (value: string): string => {
17
+ if (typeof value !== 'string') {
18
+ throw new Error(
19
+ `Value must be a string, instead got: ${JSON.stringify(value)}`,
20
+ )
21
+ }
22
+ return value.replace(/'/g, "''")
23
+ }
24
+ export const getObjectForRow = (row: any): ResultObject => {
25
+ const obj: ResultObject = {}
26
+
27
+ row.columnNames.forEach((colName, index) => {
28
+ const value = row.row[index]
29
+ if (typeof value !== 'string') {
30
+ obj[colName] = row.row[index]
31
+ return
32
+ }
33
+
34
+ // Try to parse the value as JSON
35
+ try {
36
+ obj[colName] = JSON.parse(value)
37
+ } catch (e) {
38
+ // If it fails, just set the value as a string
39
+ obj[colName] = value
40
+ }
41
+ })
42
+
43
+ return obj
44
+ }
45
+ export const getSqlResultObject = (
46
+ queryResult: DbQueryResult,
47
+ ): ResultObject | ResultObject[] | undefined => {
48
+ if (!queryResult || !queryResult.rows || queryResult.rows.length === 0) {
49
+ return
50
+ }
51
+
52
+ let obj: ResultObject | ResultObject[] | undefined
53
+
54
+ if (queryResult.rows.length === 1) {
55
+ obj = getObjectForRow(queryResult.rows[0])
56
+ }
57
+
58
+ if (queryResult.rows.length > 1) {
59
+ obj = queryResult.rows.reduce((acc, row) => {
60
+ const rowObj = getObjectForRow(row)
61
+
62
+ acc.push(rowObj)
63
+ return acc
64
+ }, [] as ResultObject[])
65
+ }
66
+
67
+ return obj
68
+ }
69
+ export const createOrUpdate = async <T>(
70
+ db: BetterSQLite3Database | SqliteRemoteDatabase,
71
+ table: SQLiteTableWithColumns<any>,
72
+ values: Partial<Record<keyof T, T[keyof T]>>,
73
+ ) => {
74
+ const startTime = Date.now()
75
+
76
+ const valueFilters: SQL[] = []
77
+
78
+ const propertiesToExcludeFromDb = ['ref']
79
+
80
+ const safeValues = Object.keys(values).reduce(
81
+ (acc, key) => {
82
+ if (!propertiesToExcludeFromDb.includes(key)) {
83
+ acc[key] = values[key as string & keyof T]
84
+ }
85
+ return acc
86
+ },
87
+ {} as Record<string, unknown>,
88
+ )
89
+
90
+ for (const [key, value] of Object.entries(safeValues)) {
91
+ let finalValue = value
92
+ if (key === 'TObject') {
93
+ continue
94
+ }
95
+ if (typeof value === 'object') {
96
+ finalValue = JSON.stringify(value)
97
+ }
98
+ const column = table[key]
99
+ if (!column) {
100
+ throw new Error(`Column not found for ${key}`)
101
+ }
102
+ if (typeof finalValue === 'undefined') {
103
+ finalValue = null
104
+ }
105
+ if (finalValue === null) {
106
+ valueFilters.push(isNull(table[key]))
107
+ continue
108
+ }
109
+ valueFilters.push(eq(table[key], finalValue))
110
+ }
111
+
112
+ const doneWithFilters = Date.now()
113
+
114
+ // console.log('valueFilters:', valueFilters)
115
+
116
+ // for ( const filter of valueFilters ) {
117
+ // console.log('filter:', Object.keys(filter))
118
+ // }
119
+
120
+ // Build a query to find the record based on properties
121
+ const existingRecords = await db
122
+ .select()
123
+ .from(table)
124
+ .where(and(...valueFilters))
125
+
126
+ const doneWithExistingRecords = Date.now()
127
+
128
+ if (existingRecords.length > 1) {
129
+ throw new Error('Multiple records found')
130
+ }
131
+
132
+ if (existingRecords.length > 0) {
133
+ // If record exists, update it
134
+ await db
135
+ .update(table)
136
+ .set(safeValues)
137
+ .where(and(...valueFilters))
138
+ console.log('updatedRecord:', {
139
+ ...existingRecords[0],
140
+ ...safeValues,
141
+ })
142
+
143
+ const doneWithUpdate = Date.now()
144
+
145
+ console.log(
146
+ '[helpers/db] [createOrUpdate] filters duration:',
147
+ doneWithFilters - startTime,
148
+ )
149
+ console.log(
150
+ '[helpers/db] [createOrUpdate] existingRecords duration:',
151
+ doneWithExistingRecords - doneWithFilters,
152
+ )
153
+ console.log(
154
+ '[helpers/db] [createOrUpdate] update duration:',
155
+ doneWithUpdate - doneWithExistingRecords,
156
+ )
157
+
158
+ return existingRecords[0] as T
159
+ } else {
160
+ // If no record exists, create a new one
161
+ const newRecord = await db.insert(table).values(safeValues).returning()
162
+ console.log('newRecord:', newRecord)
163
+ return newRecord[0] as T
164
+ }
165
+ }
166
+ export const addModelsToInternalDb = async (
167
+ db: BetterSQLite3Database<any> | SqliteRemoteDatabase<any>,
168
+ models: ModelDefinitions,
169
+ ) => {
170
+ for (const [modelName, modelClass] of Object.entries(models)) {
171
+ console.log(
172
+ '[helpers/db] [addModelsToInternalDb] starting modelName:',
173
+ modelName,
174
+ )
175
+ const modelRecord = await createOrUpdate<NewModelRecord>(db, modelsTable, {
176
+ name: modelName,
177
+ })
178
+
179
+ for (let [propertyName, propertyValues] of Object.entries(
180
+ modelClass.schema,
181
+ )) {
182
+ if (!propertyValues) {
183
+ throw new Error(`Property values not found for ${propertyName}`)
184
+ }
185
+ propertyValues.name = propertyName
186
+ propertyValues.modelId = modelRecord.id!
187
+ for (let [key, value] of Object.entries(propertyValues)) {
188
+ if (key === 'ref') {
189
+ const refModel = await createOrUpdate<NewModelRecord>(
190
+ db,
191
+ modelsTable,
192
+ {
193
+ name: value,
194
+ },
195
+ )
196
+ // delete propertyValues.ref
197
+ propertyValues.refModelId = refModel.id
198
+ }
199
+ }
200
+
201
+ const propertyRecord = await createOrUpdate<NewPropertyRecord>(
202
+ db,
203
+ properties,
204
+ propertyValues,
205
+ )
206
+
207
+ console.log('propertyRecord:', propertyRecord)
208
+ }
209
+
210
+ console.log(
211
+ '[helpers/db] [addModelsToInternalDb] done modelName:',
212
+ modelName,
213
+ )
214
+ }
215
+ }
216
+ export const getAddressesFromDb = async (): Promise<string[]> => {
217
+ const appDb = getAppDb()
218
+
219
+ if (!appDb) {
220
+ return new Promise((resolve) => {
221
+ setTimeout(async () => {
222
+ const addresses = await getAddressesFromDb()
223
+ resolve(addresses)
224
+ }, 500)
225
+ })
226
+ }
227
+
228
+ const appStatesRecords = await appDb!
229
+ .select()
230
+ .from(appState)
231
+ .where(eq(appState.key, 'addresses'))
232
+ .limit(1)
233
+
234
+ if (!appStatesRecords || appStatesRecords.length === 0) {
235
+ throw new Error('No appStatesRecords for addresses found')
236
+ }
237
+
238
+ const addressRecord = appStatesRecords[0]
239
+
240
+ const addressArrayString = addressRecord.value
241
+
242
+ if (!addressArrayString) {
243
+ throw new Error('No addresses found')
244
+ }
245
+
246
+ return JSON.parse(addressArrayString)
247
+ }