refactor: introduce domain model classes and mapper layer
Replace ad-hoc inline row casting (snake_case → camelCase) spread across services, routes, and the indexing pipeline with explicit model classes (Repository, IndexingJob, RepositoryVersion, Snippet, SearchResult) and dedicated mapper classes that own the DB → domain conversion. - Add src/lib/server/models/ with typed model classes for all domain entities - Add src/lib/server/mappers/ with mapper classes per entity - Remove duplicated RawRow interfaces and inline map functions from job-queue, repository.service, indexing.pipeline, and all API routes - Add dtoJsonResponse helper to standardise JSON responses via SvelteKit json() - Add api-contract.integration.test.ts as a regression baseline Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -115,26 +115,19 @@ describe('VersionService.list()', () => {
|
||||
describe('VersionService.add()', () => {
|
||||
it('creates a version with the correct ID format', () => {
|
||||
const { versionService } = setup();
|
||||
const version = versionService.add(
|
||||
'/facebook/react',
|
||||
'v18.3.0',
|
||||
'React v18.3.0'
|
||||
) as unknown as RawVersion;
|
||||
const version = versionService.add('/facebook/react', 'v18.3.0', 'React v18.3.0');
|
||||
expect(version.id).toBe('/facebook/react/v18.3.0');
|
||||
expect(version.repository_id).toBe('/facebook/react');
|
||||
expect(version.repositoryId).toBe('/facebook/react');
|
||||
expect(version.tag).toBe('v18.3.0');
|
||||
expect(version.title).toBe('React v18.3.0');
|
||||
expect(version.state).toBe('pending');
|
||||
expect(version.total_snippets).toBe(0);
|
||||
expect(version.indexed_at).toBeNull();
|
||||
expect(version.totalSnippets).toBe(0);
|
||||
expect(version.indexedAt).toBeNull();
|
||||
});
|
||||
|
||||
it('creates a version without a title', () => {
|
||||
const { versionService } = setup();
|
||||
const version = versionService.add(
|
||||
'/facebook/react',
|
||||
'v18.3.0'
|
||||
) as unknown as RawVersion;
|
||||
const version = versionService.add('/facebook/react', 'v18.3.0');
|
||||
expect(version.title).toBeNull();
|
||||
});
|
||||
|
||||
@@ -154,7 +147,7 @@ describe('VersionService.add()', () => {
|
||||
// Use a repo name without dots so resolveGitHubId produces a predictable ID.
|
||||
repoService.add({ source: 'github', sourceUrl: 'https://github.com/vercel/nextjs' });
|
||||
versionService.add('/facebook/react', 'v18.3.0');
|
||||
const v = versionService.add('/vercel/nextjs', 'v18.3.0') as unknown as RawVersion;
|
||||
const v = versionService.add('/vercel/nextjs', 'v18.3.0');
|
||||
expect(v.id).toBe('/vercel/nextjs/v18.3.0');
|
||||
});
|
||||
});
|
||||
@@ -211,13 +204,11 @@ describe('VersionService.getByTag()', () => {
|
||||
it('returns the version record when it exists', () => {
|
||||
const { versionService } = setup();
|
||||
versionService.add('/facebook/react', 'v18.3.0', 'React v18.3.0');
|
||||
const version = versionService.getByTag(
|
||||
'/facebook/react',
|
||||
'v18.3.0'
|
||||
) as unknown as RawVersion;
|
||||
const version = versionService.getByTag('/facebook/react', 'v18.3.0');
|
||||
expect(version).not.toBeNull();
|
||||
if (!version) throw new Error('Expected version to exist');
|
||||
expect(version.tag).toBe('v18.3.0');
|
||||
expect(version.repository_id).toBe('/facebook/react');
|
||||
expect(version?.repositoryId).toBe('/facebook/react');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -266,10 +257,8 @@ describe('VersionService.registerFromConfig()', () => {
|
||||
versionService.registerFromConfig('/facebook/react', [
|
||||
{ tag: 'v18.3.0', title: 'React v18.3.0' }
|
||||
]);
|
||||
const version = versionService.getByTag(
|
||||
'/facebook/react',
|
||||
'v18.3.0'
|
||||
) as unknown as RawVersion;
|
||||
const version = versionService.getByTag('/facebook/react', 'v18.3.0');
|
||||
if (!version) throw new Error('Expected version to exist');
|
||||
expect(version.state).toBe('pending');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user