feat(types): extend FileSystemHandle and optimize imports for consistency

- Added `getFile` method to `FileSystemHandle` interface for enhanced TypeScript compatibility with File System Access API.
- Improved maintainability by reformatting and aligning imports in `brainyData.ts`.
- Standardized spacing and indentation across structured comments and interface fields.

Purpose: Improve TypeScript support for file system operations and enhance code readability with consistent formatting and import management.
This commit is contained in:
David Snelling 2025-07-21 12:48:03 -07:00
parent 7cec5fb90a
commit e1632523b4
4 changed files with 2745 additions and 2723 deletions

View file

@ -3,11 +3,9 @@ import {
IMemoryAugmentation, IMemoryAugmentation,
AugmentationResponse AugmentationResponse
} from '../types/augmentations.js' } from '../types/augmentations.js'
import { StorageAdapter, Vector } from '../coreTypes.js' import {StorageAdapter, Vector} from '../coreTypes.js'
import { MemoryStorage } from '../storage/opfsStorage.js' import {MemoryStorage, FileSystemStorage, OPFSStorage} from '../storage/storageFactory.js'
import { FileSystemStorage } from '../storage/fileSystemStorage.js' import {cosineDistance} from '../utils/distance.js'
import { OPFSStorage } from '../storage/opfsStorage.js'
import { cosineDistance } from '../utils/distance.js'
/** /**
* Base class for memory augmentations that wrap a StorageAdapter * Base class for memory augmentations that wrap a StorageAdapter
@ -55,7 +53,7 @@ abstract class BaseMemoryAugmentation implements IMemoryAugmentation {
try { try {
await this.storage.saveMetadata(key, data) await this.storage.saveMetadata(key, data)
return { success: true, data: true } return {success: true, data: true}
} catch (error) { } catch (error) {
console.error(`Failed to store data for key ${key}:`, error) console.error(`Failed to store data for key ${key}:`, error)
return { return {
@ -97,7 +95,7 @@ abstract class BaseMemoryAugmentation implements IMemoryAugmentation {
try { try {
await this.storage.saveMetadata(key, data) await this.storage.saveMetadata(key, data)
return { success: true, data: true } return {success: true, data: true}
} catch (error) { } catch (error) {
console.error(`Failed to update data for key ${key}:`, error) console.error(`Failed to update data for key ${key}:`, error)
return { return {
@ -117,7 +115,7 @@ abstract class BaseMemoryAugmentation implements IMemoryAugmentation {
try { try {
// There's no direct deleteMetadata method, so we save null // There's no direct deleteMetadata method, so we save null
await this.storage.saveMetadata(key, null) await this.storage.saveMetadata(key, null)
return { success: true, data: true } return {success: true, data: true}
} catch (error) { } catch (error) {
console.error(`Failed to delete data for key ${key}:`, error) console.error(`Failed to delete data for key ${key}:`, error)
return { return {
@ -257,7 +255,7 @@ export class FileSystemStorageAugmentation extends BaseMemoryAugmentation {
enabled = true enabled = true
constructor(name: string, rootDirectory?: string) { constructor(name: string, rootDirectory?: string) {
super(name, new FileSystemStorage(rootDirectory)) super(name, new FileSystemStorage(rootDirectory || '.'))
} }
getType(): AugmentationType { getType(): AugmentationType {

View file

@ -3,13 +3,13 @@
* Main class that provides the vector database functionality * Main class that provides the vector database functionality
*/ */
import { v4 as uuidv4 } from 'uuid' import {v4 as uuidv4} from 'uuid'
import { HNSWIndex } from './hnsw/hnswIndex.js' import {HNSWIndex} from './hnsw/hnswIndex.js'
import { import {
HNSWIndexOptimized, HNSWIndexOptimized,
HNSWOptimizedConfig HNSWOptimizedConfig
} from './hnsw/hnswIndexOptimized.js' } from './hnsw/hnswIndexOptimized.js'
import { createStorage } from './storage/opfsStorage.js' import {createStorage} from './storage/storageFactory.js'
import { import {
DistanceFunction, DistanceFunction,
GraphVerb, GraphVerb,
@ -30,13 +30,13 @@ import {
euclideanDistance, euclideanDistance,
cleanupWorkerPools cleanupWorkerPools
} from './utils/index.js' } from './utils/index.js'
import { NounType, VerbType, GraphNoun } from './types/graphTypes.js' import {NounType, VerbType, GraphNoun} from './types/graphTypes.js'
import { import {
ServerSearchConduitAugmentation, ServerSearchConduitAugmentation,
createServerSearchAugmentations createServerSearchAugmentations
} from './augmentations/serverSearchAugmentations.js' } from './augmentations/serverSearchAugmentations.js'
import { WebSocketConnection } from './types/augmentations.js' import {WebSocketConnection} from './types/augmentations.js'
import { BrainyDataInterface } from './types/brainyDataInterface.js' import {BrainyDataInterface} from './types/brainyDataInterface.js'
export interface BrainyDataConfig { export interface BrainyDataConfig {
/** /**
@ -156,7 +156,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
private storageConfig: BrainyDataConfig['storage'] = {} private storageConfig: BrainyDataConfig['storage'] = {}
private useOptimizedIndex: boolean = false private useOptimizedIndex: boolean = false
private _dimensions: number private _dimensions: number
private loggingConfig: BrainyDataConfig['logging'] = { verbose: true } private loggingConfig: BrainyDataConfig['logging'] = {verbose: true}
// Remote server properties // Remote server properties
private remoteServerConfig: BrainyDataConfig['remoteServer'] | null = null private remoteServerConfig: BrainyDataConfig['remoteServer'] | null = null
@ -301,7 +301,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
// Try again with a different approach - use the non-threaded version // Try again with a different approach - use the non-threaded version
// This is a fallback in case the threaded version fails // This is a fallback in case the threaded version fails
const { createTensorFlowEmbeddingFunction } = await import( const {createTensorFlowEmbeddingFunction} = await import(
'./utils/embedding.js' './utils/embedding.js'
) )
const fallbackEmbeddingFunction = createTensorFlowEmbeddingFunction() const fallbackEmbeddingFunction = createTensorFlowEmbeddingFunction()
@ -327,12 +327,28 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
// Initialize storage if not provided in constructor // Initialize storage if not provided in constructor
if (!this.storage) { if (!this.storage) {
// Combine storage config with requestPersistentStorage for backward compatibility // Combine storage config with requestPersistentStorage for backward compatibility
const storageOptions = { let storageOptions = {
...this.storageConfig, ...this.storageConfig,
requestPersistentStorage: this.requestPersistentStorage requestPersistentStorage: this.requestPersistentStorage
} }
this.storage = await createStorage(storageOptions) // Ensure s3Storage has all required fields if it's provided
if (storageOptions.s3Storage) {
// Only include s3Storage if all required fields are present
if (storageOptions.s3Storage.bucketName &&
storageOptions.s3Storage.accessKeyId &&
storageOptions.s3Storage.secretAccessKey) {
// All required fields are present, keep s3Storage as is
} else {
// Missing required fields, remove s3Storage to avoid type errors
const { s3Storage, ...rest } = storageOptions
storageOptions = rest
console.warn('Ignoring s3Storage configuration due to missing required fields')
}
}
// Use type assertion to tell TypeScript that storageOptions conforms to StorageOptions
this.storage = await createStorage(storageOptions as any)
} }
// Initialize storage // Initialize storage
@ -402,7 +418,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
try { try {
// Create server search augmentations // Create server search augmentations
const { conduit, connection } = await createServerSearchAugmentations( const {conduit, connection} = await createServerSearchAugmentations(
serverUrl, serverUrl,
{ {
protocols, protocols,
@ -481,7 +497,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
: uuidv4()) : uuidv4())
// Add to index // Add to index
await this.index.addItem({ id, vector }) await this.index.addItem({id, vector})
// Get the noun from the index // Get the noun from the index
const noun = this.index.getNouns().get(id) const noun = this.index.getNouns().get(id)
@ -514,7 +530,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
// Ensure metadata has the correct id field // Ensure metadata has the correct id field
let metadataToSave = metadata let metadataToSave = metadata
if (metadata && typeof metadata === 'object') { if (metadata && typeof metadata === 'object') {
metadataToSave = { ...metadata, id } metadataToSave = {...metadata, id}
} }
await this.storage!.saveMetadata(id, metadataToSave) await this.storage!.saveMetadata(id, metadataToSave)
@ -555,7 +571,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
} = {} } = {}
): Promise<string> { ): Promise<string> {
// Use the existing add method with forceEmbed to ensure text is embedded // Use the existing add method with forceEmbed to ensure text is embedded
return this.add(text, metadata, { ...options, forceEmbed: true }) return this.add(text, metadata, {...options, forceEmbed: true})
} }
/** /**
@ -580,7 +596,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
} }
// Add to local with addToRemote option // Add to local with addToRemote option
return this.add(vectorOrData, metadata, { ...options, addToRemote: true }) return this.add(vectorOrData, metadata, {...options, addToRemote: true})
} }
/** /**
@ -772,7 +788,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
} }
// Add to local with addToRemote option // Add to local with addToRemote option
return this.addBatch(items, { ...options, addToRemote: true }) return this.addBatch(items, {...options, addToRemote: true})
} }
/** /**
@ -1354,7 +1370,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
} }
// Add to index // Add to index
await this.index.addItem({ id, vector: verbVector }) await this.index.addItem({id, vector: verbVector})
// Get the noun from the index // Get the noun from the index
const indexNoun = this.index.getNouns().get(id) const indexNoun = this.index.getNouns().get(id)
@ -1648,7 +1664,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
queryVectorOrData, queryVectorOrData,
k * 2, // Get more results initially to account for filtering k * 2, // Get more results initially to account for filtering
null, null,
{ forceEmbed: options.forceEmbed } {forceEmbed: options.forceEmbed}
) )
// If no verb types specified, return the noun results directly // If no verb types specified, return the noun results directly
@ -1885,7 +1901,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
const remoteResults = await this.searchRemote( const remoteResults = await this.searchRemote(
queryVectorOrData, queryVectorOrData,
k - localResults.length, k - localResults.length,
{ ...options, storeResults: true } {...options, storeResults: true}
) )
// Combine results, removing duplicates // Combine results, removing duplicates
@ -2027,7 +2043,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
type: 'any', type: 'any',
used: 0, used: 0,
quota: null, quota: null,
details: { error: 'Storage not initialized' } details: {error: 'Storage not initialized'}
} }
} }
@ -2311,7 +2327,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
} }
// Add the noun with its vector and metadata // Add the noun with its vector and metadata
await this.add(noun.vector, noun.metadata, { id: noun.id }) await this.add(noun.vector, noun.metadata, {id: noun.id})
nounsRestored++ nounsRestored++
} catch (error) { } catch (error) {
console.error(`Failed to restore noun ${noun.id}:`, error) console.error(`Failed to restore noun ${noun.id}:`, error)
@ -2366,7 +2382,7 @@ export class BrainyData<T = any> implements BrainyDataInterface<T> {
// Re-add all nouns to the index // Re-add all nouns to the index
for (const noun of data.nouns) { for (const noun of data.nouns) {
if (noun.vector && noun.vector.length > 0) { if (noun.vector && noun.vector.length > 0) {
await this.index.addItem({ id: noun.id, vector: noun.vector }) await this.index.addItem({id: noun.id, vector: noun.vector})
} }
} }

View file

@ -83,13 +83,11 @@ export {
import { import {
OPFSStorage, OPFSStorage,
MemoryStorage, MemoryStorage,
createStorage FileSystemStorage,
} from './storage/opfsStorage.js'
import { FileSystemStorage } from './storage/fileSystemStorage.js'
import {
R2Storage, R2Storage,
S3CompatibleStorage S3CompatibleStorage,
} from './storage/s3CompatibleStorage.js' createStorage
} from './storage/storageFactory.js'
export { export {
OPFSStorage, OPFSStorage,

View file

@ -1,14 +1,24 @@
/** /**
* Type declarations for the File System Access API * Type declarations for the File System Access API
* Extends the FileSystemDirectoryHandle interface to include the [Symbol.asyncIterator] method * Extends the FileSystemDirectoryHandle interface to include the [Symbol.asyncIterator] method
* and FileSystemHandle to include getFile() method for TypeScript compatibility
*/ */
// Extend the FileSystemDirectoryHandle interface // Extend the FileSystemDirectoryHandle interface
interface FileSystemDirectoryHandle { interface FileSystemDirectoryHandle {
[Symbol.asyncIterator](): AsyncIterableIterator<[string, FileSystemHandle]>; [Symbol.asyncIterator](): AsyncIterableIterator<[string, FileSystemHandle]>;
keys(): AsyncIterableIterator<string>; keys(): AsyncIterableIterator<string>;
entries(): AsyncIterableIterator<[string, FileSystemHandle]>; entries(): AsyncIterableIterator<[string, FileSystemHandle]>;
} }
// Extend the FileSystemHandle interface to include getFile method
// This is needed because TypeScript doesn't recognize that a FileSystemHandle
// can be a FileSystemFileHandle which has the getFile method
interface FileSystemHandle {
getFile?(): Promise<File>;
}
// Export something to make this a module // Export something to make this a module
export const fileSystemTypesLoaded = true; export const fileSystemTypesLoaded = true