feat: implement comprehensive type safety system with BrainyTypes API
Major enhancements for type safety and developer experience: - Add BrainyTypes static API for type management and AI-powered suggestions - Implement strict type validation for all 31 NounType categories - Remove dangerous generic add() method that bypassed type safety - Add intelligent type inference with confidence scoring - Provide helpful error messages with typo suggestions using Levenshtein distance - Update all internal code, examples, and documentation to use typed methods - Enhance CLI with new type management commands (types, suggest, validate) Breaking changes: - Remove deprecated add() method - use addNoun() with explicit type parameter - All addNoun() calls now require explicit type as second parameter This release significantly improves type safety across the entire system while maintaining backward compatibility for properly typed method calls. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
d7d2d749b6
commit
6c62bc4e9d
40 changed files with 1704 additions and 497 deletions
103
tests/type-enforcement.test.ts
Normal file
103
tests/type-enforcement.test.ts
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
import { describe, it, expect, beforeEach } from 'vitest'
|
||||
import { BrainyData } from '../src/brainyData.js'
|
||||
import { NounType, VerbType } from '../src/types/graphTypes.js'
|
||||
import { validateNounType, validateVerbType } from '../src/utils/typeValidation.js'
|
||||
|
||||
describe('Type Enforcement System', () => {
|
||||
describe('Type Validation Module', () => {
|
||||
it('should validate correct noun types', () => {
|
||||
expect(validateNounType(NounType.Person)).toBe('person')
|
||||
expect(validateNounType('organization')).toBe('organization')
|
||||
expect(validateNounType(NounType.Document)).toBe('document')
|
||||
})
|
||||
|
||||
it('should reject invalid noun types with helpful errors', () => {
|
||||
expect(() => validateNounType('invalid')).toThrow('Invalid noun type')
|
||||
expect(() => validateNounType('')).toThrow('Invalid noun type')
|
||||
expect(() => validateNounType(null)).toThrow('Invalid noun type')
|
||||
expect(() => validateNounType(undefined)).toThrow('Invalid noun type')
|
||||
})
|
||||
|
||||
it('should provide helpful suggestions for typos', () => {
|
||||
expect(() => validateNounType('persan')).toThrow(/Did you mean 'person'/)
|
||||
expect(() => validateNounType('doc')).toThrow(/Did you mean 'document'/)
|
||||
expect(() => validateNounType('org')).toThrow(/Did you mean 'organization'/)
|
||||
})
|
||||
|
||||
it('should validate correct verb types', () => {
|
||||
expect(validateVerbType(VerbType.RelatedTo)).toBe('relatedTo')
|
||||
expect(validateVerbType('contains')).toBe('contains')
|
||||
expect(validateVerbType(VerbType.Creates)).toBe('creates')
|
||||
})
|
||||
})
|
||||
|
||||
describe('addNoun with Type Enforcement', () => {
|
||||
let brain: BrainyData
|
||||
|
||||
beforeEach(async () => {
|
||||
brain = new BrainyData({
|
||||
storage: { forceMemoryStorage: true },
|
||||
logging: { verbose: false }
|
||||
})
|
||||
await brain.init()
|
||||
})
|
||||
|
||||
it('should require noun type parameter', async () => {
|
||||
// TypeScript should prevent this, but test runtime validation
|
||||
await expect(
|
||||
(brain.addNoun as any)('Test data', { title: 'Test' })
|
||||
).rejects.toThrow()
|
||||
})
|
||||
|
||||
it('should accept valid noun type', async () => {
|
||||
const id = await brain.addNoun('John Doe', NounType.Person, { age: 30 })
|
||||
expect(id).toBeDefined()
|
||||
|
||||
const noun = await brain.getNoun(id)
|
||||
expect(noun.metadata.noun).toBe('person')
|
||||
expect(noun.metadata.age).toBe(30)
|
||||
})
|
||||
|
||||
it('should accept noun type as string', async () => {
|
||||
const id = await brain.addNoun('Document content', 'document', {
|
||||
title: 'Important Doc',
|
||||
author: 'Jane'
|
||||
})
|
||||
expect(id).toBeDefined()
|
||||
|
||||
const noun = await brain.getNoun(id)
|
||||
expect(noun.metadata.noun).toBe('document')
|
||||
expect(noun.metadata.title).toBe('Important Doc')
|
||||
})
|
||||
|
||||
it('should validate noun type and reject invalid ones', async () => {
|
||||
await expect(
|
||||
brain.addNoun('Test', 'invalidType', {})
|
||||
).rejects.toThrow('Invalid noun type')
|
||||
})
|
||||
|
||||
it('should provide suggestions for typos', async () => {
|
||||
await expect(
|
||||
brain.addNoun('Test', 'persan', {})
|
||||
).rejects.toThrow(/Did you mean 'person'/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Type Validation Performance', () => {
|
||||
it('should validate types quickly (O(1) with Set)', () => {
|
||||
const start = performance.now()
|
||||
|
||||
// Validate 10000 types
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
validateNounType(NounType.Person)
|
||||
validateVerbType(VerbType.Contains)
|
||||
}
|
||||
|
||||
const end = performance.now()
|
||||
const duration = end - start
|
||||
|
||||
// Should complete in less than 50ms (very generous, usually < 5ms)
|
||||
expect(duration).toBeLessThan(50)
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue