chore(LINT-0001) fix lint errors

This commit is contained in:
Giancarmine Salucci
2026-03-27 03:01:37 +01:00
parent 7f7d806172
commit da661efc91
24 changed files with 114 additions and 69 deletions

View File

@@ -299,7 +299,6 @@ describe('LocalCrawler.crawl() — lock file and minified file exclusions', () =
'src/index.ts': 'export {};',
'dist/vendor.min.js': '!function(e,t){}()'
});
const result = await crawlRoot();
// dist/ is pruned by default — test via shouldIndexFile logic only if .gitignore present
// Use a custom path outside ignored dirs:
await fs.rm(root, { recursive: true, force: true });

View File

@@ -266,7 +266,7 @@ describe('Migration — embedding_profiles', () => {
const { client } = createTestDb();
const row = client
.prepare("SELECT * FROM embedding_profiles WHERE id = 'local-default'")
.get() as any;
.get() as Record<string, unknown>;
expect(row).toBeDefined();
expect(row.is_default).toBe(1);
expect(row.provider_kind).toBe('local-transformers');

View File

@@ -9,6 +9,19 @@
import { EmbeddingError, type EmbeddingProvider, type EmbeddingVector } from './provider.js';
type LocalEmbeddingResult = {
data: ArrayLike<number>;
};
type LocalEmbeddingPipeline = (
text: string,
options: Record<string, unknown>
) => Promise<LocalEmbeddingResult>;
type TransformersModule = {
pipeline: (task: string, model: string) => Promise<LocalEmbeddingPipeline>;
};
export class LocalEmbeddingProvider implements EmbeddingProvider {
readonly name = 'local';
readonly model = 'Xenova/all-MiniLM-L6-v2';
@@ -20,13 +33,11 @@ export class LocalEmbeddingProvider implements EmbeddingProvider {
async embed(texts: string[]): Promise<EmbeddingVector[]> {
if (!this.pipeline) {
let transformers: { pipeline: Function };
let transformers: TransformersModule;
try {
// Dynamic import — only succeeds when @xenova/transformers is installed.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
transformers = (await import('@xenova/transformers' as any)) as {
pipeline: Function;
};
transformers = (await import('@xenova/transformers' as any)) as TransformersModule;
} catch {
throw new EmbeddingError(
'@xenova/transformers is not installed. Install it to use the local embedding provider.'

View File

@@ -37,7 +37,8 @@ export class NoopEmbeddingProvider implements EmbeddingProvider {
readonly dimensions = 0;
readonly model = 'none';
async embed(_texts: string[]): Promise<EmbeddingVector[]> {
async embed(texts: string[]): Promise<EmbeddingVector[]> {
void texts;
return [];
}

View File

@@ -14,7 +14,7 @@ import type { EmbeddingProfile } from '../db/schema.js';
export type ProviderFactory = (config: Record<string, unknown>) => EmbeddingProvider;
const PROVIDER_REGISTRY: Record<string, ProviderFactory> = {
'local-transformers': (_config) => new LocalEmbeddingProvider(),
'local-transformers': () => new LocalEmbeddingProvider(),
'openai-compatible': (config) =>
new OpenAIEmbeddingProvider({
baseUrl: config.baseUrl as string,

View File

@@ -124,7 +124,7 @@ export class CodeListItemDto {
}
export class CodeSnippetJsonDto {
type: 'code' = 'code';
readonly type = 'code' as const;
title: string | null;
description: string | null;
language: string | null;
@@ -147,7 +147,7 @@ export class CodeSnippetJsonDto {
}
export class InfoSnippetJsonDto {
type: 'info' = 'info';
readonly type = 'info' as const;
text: string;
breadcrumb: string | null;
pageId: string;

View File

@@ -32,9 +32,9 @@ export const BOUNDARY_PATTERNS: Record<string, RegExp> = {
python: /^(async\s+)?(def|class)\s+\w+/,
go: /^(func|type|var|const)\s+\w+/,
rust: /^(pub(\s*\(crate\))?\s+)?(async\s+)?(fn|impl|struct|enum|trait|type|const|static)\s+\w+/,
java: /^(\s*(public|private|protected|static|final|abstract|synchronized)\s+)+[\w<>\[\]]+\s+\w+\s*[({]/,
java: /^(\s*(public|private|protected|static|final|abstract|synchronized)\s+)+[\w<>[\]]+\s+\w+\s*[({]/,
csharp:
/^(\s*(public|private|protected|internal|static|override|virtual|abstract|sealed)\s+)+[\w<>\[\]]+\s+\w+\s*[({]/,
/^(\s*(public|private|protected|internal|static|override|virtual|abstract|sealed)\s+)+[\w<>[\]]+\s+\w+\s*[({]/,
kotlin:
/^(\s*(public|private|protected|internal|override|suspend|inline|open|abstract|sealed)\s+)*(fun|class|object|interface|data class|sealed class|enum class)\s+\w+/,
swift:
@@ -111,7 +111,7 @@ function slidingWindowChunks(content: string, filePath: string, language: string
* followed by colon/equals/brace) and treat each as a boundary.
*/
function parseConfigFile(content: string, filePath: string, language: string): RawSnippet[] {
const topLevelKey = /^[\w"'\-]+\s*[:=\[{]/;
const topLevelKey = /^[\w"'-]+\s*[:=[{]/;
const lines = content.split('\n');
const segments: string[] = [];
let current: string[] = [];

View File

@@ -13,7 +13,7 @@
* - With embeddings : crawl+parse = 80 %, embeddings = 20 %
*/
import { createHash } from 'node:crypto';
import { createHash, randomUUID } from 'node:crypto';
import type Database from 'better-sqlite3';
import type { Document, NewDocument, NewSnippet } from '$lib/types';
import type { crawl as GithubCrawlFn } from '$lib/server/crawler/github.crawler.js';
@@ -92,7 +92,7 @@ export class IndexingPipeline {
this.updateRepo(repo.id, { state: 'indexing' });
// ---- Stage 1: Crawl -------------------------------------------------
const crawlResult = await this.crawl(repo, normJob);
const crawlResult = await this.crawl(repo);
const totalFiles = crawlResult.totalFiles;
this.updateJob(job.id, { totalFiles });
@@ -140,7 +140,7 @@ export class IndexingPipeline {
const checksum = file.sha || sha256(file.content);
// Create new document record.
const documentId = crypto.randomUUID();
const documentId = randomUUID();
const now = new Date();
const newDoc: NewDocument = {
id: documentId,
@@ -247,10 +247,7 @@ export class IndexingPipeline {
// Private — crawl
// -------------------------------------------------------------------------
private async crawl(
repo: Repository,
job: IndexingJob
): Promise<{
private async crawl(repo: Repository): Promise<{
files: Array<{ path: string; content: string; sha: string; size: number; language: string }>;
totalFiles: number;
}> {

View File

@@ -153,7 +153,7 @@ function makeNoopProvider(): EmbeddingProvider {
name: 'noop',
dimensions: 0,
model: 'none',
async embed(_texts: string[]): Promise<EmbeddingVector[]> {
async embed(): Promise<EmbeddingVector[]> {
return [];
},
async isAvailable(): Promise<boolean> {
@@ -738,7 +738,7 @@ describe('HybridSearchService', () => {
const repoId = seedRepo(client);
const docId = seedDocument(client, repoId);
const snippetId = seedSnippet(client, {
seedSnippet(client, {
repositoryId: repoId,
documentId: docId,
content: 'keyword only test'
@@ -860,7 +860,7 @@ describe('HybridSearchService', () => {
it('searchMode=semantic returns empty array for blank query', async () => {
const client = createTestDb();
const repoId = seedRepo(client);
const docId = seedDocument(client, repoId);
seedDocument(client, repoId);
const mockProvider = makeMockProvider([[1, 0, 0, 0]]);
@@ -879,7 +879,7 @@ describe('HybridSearchService', () => {
it('searchMode=semantic falls back to empty when provider fails', async () => {
const client = createTestDb();
const repoId = seedRepo(client);
const docId = seedDocument(client, repoId);
seedDocument(client, repoId);
const noopProvider = makeNoopProvider();
const searchService = new SearchService(client);

View File

@@ -46,8 +46,8 @@ export function preprocessQuery(raw: string): string {
.replace(/[()[\]{}]/g, ' ') // Remove grouping characters
.replace(/[;:,!?]/g, ' ') // Remove punctuation that breaks FTS
.replace(/[<>|]/g, ' ') // Remove comparison/pipe chars
.replace(/[\-+*/%]/g, ' ') // Remove operators (but keep underscores)
.replace(/[@#$&^\\~\`]/g, ' '); // Remove special chars
.replace(/[-+*/%]/g, ' ') // Remove operators (but keep underscores)
.replace(/[@#$&^~`\\]/g, ' '); // Remove special chars
// Split on remaining punctuation (like dots and slashes) but preserve alphanumeric/underscore.
const parts = sanitized.split(/[./\s]+/).filter(Boolean);

View File

@@ -62,21 +62,6 @@ interface RawRepo {
updated_at: number;
}
// Raw row shape returned by better-sqlite3 SELECT * FROM indexing_jobs.
interface RawJob {
id: string;
repository_id: string;
version_id: string | null;
status: string;
progress: number;
total_files: number;
processed_files: number;
error: string | null;
started_at: number | null;
completed_at: number | null;
created_at: number;
}
function makeService(client: Database.Database): RepositoryService {
return new RepositoryService(client);
}

View File

@@ -6,7 +6,7 @@
* output — the same pattern used by repository.service.test.ts.
*/
import { describe, it, expect, beforeEach } from 'vitest';
import { describe, it, expect } from 'vitest';
import Database from 'better-sqlite3';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';

View File

@@ -12,6 +12,7 @@ import {
RepositoryVersionEntity
} from '$lib/server/models/repository-version.js';
import { AlreadyExistsError, NotFoundError } from '$lib/server/utils/validation';
import { resolveTagToCommit, discoverVersionTags } from '$lib/server/utils/git.js';
export class VersionService {
constructor(private readonly db: Database.Database) {}
@@ -62,7 +63,6 @@ export class VersionService {
let resolvedCommitHash = commitHash;
if (!resolvedCommitHash && repo.source === 'local') {
try {
const { resolveTagToCommit } = require('$lib/server/utils/git.js');
resolvedCommitHash = resolveTagToCommit({ repoPath: repo.source_url, tag });
} catch (error) {
console.warn(
@@ -178,7 +178,6 @@ export class VersionService {
throw new Error('Tag discovery is only supported for local repositories');
}
const { discoverVersionTags, resolveTagToCommit } = require('$lib/server/utils/git.js');
const tags = discoverVersionTags({ repoPath: repo.source_url });
return tags.map((tag: string) => {