59 lines
2.4 KiB
TypeScript
59 lines
2.4 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
|
const migrationDir = path.resolve(currentDir, '../../src/infra/database/migrations');
|
|
const migrationFile = '050_create-memory-schema.sql';
|
|
const migrationPath = path.resolve(migrationDir, migrationFile);
|
|
|
|
function readMigration(): string {
|
|
return fs.readFileSync(migrationPath, 'utf8');
|
|
}
|
|
|
|
describe('create memory schema migration', () => {
|
|
it('exists and is ordered after the prior migration', () => {
|
|
expect(fs.existsSync(migrationPath)).toBe(true);
|
|
const migrations = fs
|
|
.readdirSync(migrationDir)
|
|
.filter((f) => f.endsWith('.sql'))
|
|
.sort();
|
|
const idx = migrations.indexOf(migrationFile);
|
|
const prev = migrations.indexOf('049_add-multi-provider-payments-foundation.sql');
|
|
expect(prev).not.toBe(-1);
|
|
expect(idx).toBeGreaterThan(prev);
|
|
});
|
|
|
|
it('enables pgvector and creates the memory.memories table with a 1536-d vector', () => {
|
|
const sql = readMigration();
|
|
expect(sql).toMatch(/CREATE EXTENSION IF NOT EXISTS vector/i);
|
|
expect(sql).toMatch(/CREATE SCHEMA IF NOT EXISTS memory/i);
|
|
expect(sql).toMatch(/CREATE TABLE IF NOT EXISTS memory\.memories/i);
|
|
expect(sql).toMatch(/embedding\s+VECTOR\(1536\)/i);
|
|
});
|
|
|
|
it('constrains kind to the four memory kinds', () => {
|
|
const sql = readMigration();
|
|
expect(sql).toMatch(
|
|
/kind\s+TEXT\s+NOT NULL\s+CHECK\s*\(kind IN \('fact', 'decision', 'preference', 'reference'\)\)/i
|
|
);
|
|
});
|
|
|
|
it('creates the HNSW vector index and the GIN full-text index for hybrid recall', () => {
|
|
const sql = readMigration();
|
|
expect(sql).toMatch(/USING hnsw \(embedding vector_cosine_ops\)/i);
|
|
expect(sql).toMatch(/content_tsv\s+TSVECTOR GENERATED ALWAYS AS/i);
|
|
expect(sql).toMatch(/USING gin \(content_tsv\)/i);
|
|
});
|
|
|
|
it('is idempotent on the trigger (DROP TRIGGER IF EXISTS before CREATE)', () => {
|
|
const sql = readMigration();
|
|
expect(sql).toMatch(/DROP TRIGGER IF EXISTS trg_memories_updated_at ON memory\.memories/i);
|
|
const dropIdx = sql.indexOf('DROP TRIGGER IF EXISTS trg_memories_updated_at');
|
|
const createIdx = sql.indexOf('CREATE TRIGGER trg_memories_updated_at');
|
|
expect(dropIdx).toBeGreaterThan(-1);
|
|
expect(createIdx).toBeGreaterThan(dropIdx);
|
|
});
|
|
});
|