Dinh Long Nguyen a30eb7f968
feat: Jan Web (reusing Jan Desktop UI) (#6298)
* add platform guards

* add service management

* fix types

* move to zustand for servicehub

* update App Updater

* update tauri missing move

* update app updater

* refactor: move PlatformFeatures to separate const file

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* change tauri fetch name

* update implementation

* update extension fetch

* make web version run properly

* disabled unused web settings

* fix all tests

* fix lint

* fix tests

* add mock for extension

* fix build

* update make and mise

* fix tsconfig for web-extensions

* fix loader type

* cleanup

* fix test

* update error handling + mcp should be working

* Update mcp init

* use separate is_web_app build property

* Remove fixed model catalog url

* fix additional tests

* fix download issue (event emitter not implemented correctly)

* Update Title html

* fix app logs

* update root tsx render timing

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-05 01:47:46 +07:00

105 lines
2.5 KiB
TypeScript

/**
* Shared IndexedDB utilities for web extensions
*/
import type { IndexedDBConfig } from '../types'
/**
* Default database configuration for Jan web extensions
*/
const DEFAULT_DB_CONFIG: IndexedDBConfig = {
dbName: 'jan-web-db',
version: 1,
stores: [
{
name: 'assistants',
keyPath: 'id',
indexes: [
{ name: 'name', keyPath: 'name' },
{ name: 'created_at', keyPath: 'created_at' }
]
},
{
name: 'threads',
keyPath: 'id',
indexes: [
{ name: 'title', keyPath: 'title' },
{ name: 'created_at', keyPath: 'created_at' },
{ name: 'updated_at', keyPath: 'updated_at' }
]
},
{
name: 'messages',
keyPath: 'id',
indexes: [
{ name: 'thread_id', keyPath: 'thread_id' },
{ name: 'created_at', keyPath: 'created_at' }
]
}
]
}
/**
* Shared IndexedDB instance
*/
let sharedDB: IDBDatabase | null = null
/**
* Get or create the shared IndexedDB instance
*/
export const getSharedDB = async (config: IndexedDBConfig = DEFAULT_DB_CONFIG): Promise<IDBDatabase> => {
if (sharedDB && sharedDB.name === config.dbName) {
return sharedDB
}
return new Promise((resolve, reject) => {
const request = indexedDB.open(config.dbName, config.version)
request.onerror = () => {
reject(new Error(`Failed to open database: ${request.error?.message}`))
}
request.onsuccess = () => {
sharedDB = request.result
resolve(sharedDB)
}
request.onupgradeneeded = (event) => {
const db = (event.target as IDBOpenDBRequest).result
// Create object stores
for (const store of config.stores) {
let objectStore: IDBObjectStore
if (db.objectStoreNames.contains(store.name)) {
// Store exists, might need to update indexes
continue
} else {
// Create new store
objectStore = db.createObjectStore(store.name, { keyPath: store.keyPath })
}
// Create indexes
if (store.indexes) {
for (const index of store.indexes) {
try {
objectStore.createIndex(index.name, index.keyPath, { unique: index.unique || false })
} catch (error) {
// Index might already exist, ignore
}
}
}
}
}
})
}
/**
* Close the shared database connection
*/
export const closeSharedDB = () => {
if (sharedDB) {
sharedDB.close()
sharedDB = null
}
}