feat(core, tests): add standalone getStatistics function and improve storage configuration

- **Core**: Introduced a new `getStatistics` utility function in `statistics.ts` for fetching database statistics at the root level of the library. Enhanced `BrainyData` methods to ensure metadata includes `id` field and refined statistics calculations, excluding verbs from the noun count.
- **Tests**: Added comprehensive test coverage in `statistics.test.ts` for the new utility function, validating proper error handling, statistics accuracy, and consistent results between instance methods and standalone function.
- **Storage Config**: Enabled dynamic support for AWS S3, Cloudflare R2, and Google Cloud Storage in web service configuration, utilizing environment variables for adapter setup. Addressed a race condition in `FileSystemStorage` initialization by deferring path module imports.

**Purpose**: Enhance database analytics by introducing a reusable `getStatistics` function, improve flexibility in storage configuration, and ensure robust testing for reliability and accuracy.
This commit is contained in:
David Snelling 2025-07-23 16:26:59 -07:00
parent 233aea953c
commit 1c127fe7d8
13 changed files with 346 additions and 61 deletions

View file

@ -37,25 +37,49 @@ describe('Brainy Web Service Cloud Storage Integration', () => {
let errorOutput = ''
serverProcess.stdout?.on('data', (data) => {
output += data.toString()
const dataStr = data.toString()
output += dataStr
// Check for error messages in stdout that indicate initialization failure
if (dataStr.includes('Failed to initialize') || dataStr.includes('Error:')) {
console.log(` Server stdout error: ${dataStr.trim()}`)
reject(new Error(`Server initialization failed: ${dataStr.trim()}`))
return
}
if (output.includes('Server running on')) {
resolve()
}
})
serverProcess.stderr?.on('data', (data) => {
errorOutput += data.toString()
console.log(` Server stderr: ${data.toString().trim()}`)
const dataStr = data.toString()
errorOutput += dataStr
console.log(` Server stderr: ${dataStr.trim()}`)
// Check for error messages in stderr that indicate initialization failure
if (dataStr.includes('Failed to initialize') || dataStr.includes('Error:')) {
reject(new Error(`Server initialization failed: ${dataStr.trim()}`))
}
})
serverProcess.on('error', (error) => {
reject(new Error(`Failed to start server: ${error.message}`))
})
serverProcess.on('exit', (code) => {
serverProcess.on('exit', (code, signal) => {
// If the process exited with a non-zero code, it's an error
if (code !== 0 && code !== null) {
reject(new Error(`Server exited with code ${code}. Error: ${errorOutput}`))
}
// If the process was terminated by a signal and we have error output, it's an error
else if (signal && errorOutput) {
reject(new Error(`Server terminated by signal ${signal}. Error: ${errorOutput}`))
}
// If we have error output but no code or signal, it's still an error
else if (errorOutput && errorOutput.includes('Error:')) {
reject(new Error(`Server exited with error: ${errorOutput}`))
}
})
// Timeout after 10 seconds