chore(FEEDBACK-0001): linting
This commit is contained in:
@@ -31,10 +31,12 @@ Implement the core `RepositoryService` that handles CRUD operations for reposito
|
||||
## Repository ID Generation
|
||||
|
||||
GitHub repositories:
|
||||
|
||||
- Input URL: `https://github.com/facebook/react` or `github.com/facebook/react`
|
||||
- Generated ID: `/facebook/react`
|
||||
|
||||
Local repositories:
|
||||
|
||||
- Input path: `/home/user/projects/my-sdk`
|
||||
- Generated ID: `/local/my-sdk` (basename of path, slugified)
|
||||
- Collision resolution: append `-2`, `-3`, etc.
|
||||
@@ -49,44 +51,44 @@ Version-specific IDs: `/facebook/react/v18.3.0`
|
||||
// src/lib/server/services/repository.service.ts
|
||||
|
||||
export interface AddRepositoryInput {
|
||||
source: 'github' | 'local';
|
||||
sourceUrl: string; // GitHub URL or absolute local path
|
||||
title?: string; // override auto-detected title
|
||||
description?: string;
|
||||
branch?: string; // GitHub: default branch; Local: n/a
|
||||
githubToken?: string; // for private GitHub repos
|
||||
source: 'github' | 'local';
|
||||
sourceUrl: string; // GitHub URL or absolute local path
|
||||
title?: string; // override auto-detected title
|
||||
description?: string;
|
||||
branch?: string; // GitHub: default branch; Local: n/a
|
||||
githubToken?: string; // for private GitHub repos
|
||||
}
|
||||
|
||||
export interface UpdateRepositoryInput {
|
||||
title?: string;
|
||||
description?: string;
|
||||
branch?: string;
|
||||
githubToken?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
branch?: string;
|
||||
githubToken?: string;
|
||||
}
|
||||
|
||||
export class RepositoryService {
|
||||
constructor(private db: BetterSQLite3.Database) {}
|
||||
constructor(private db: BetterSQLite3.Database) {}
|
||||
|
||||
async list(options?: {
|
||||
state?: Repository['state'];
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}): Promise<Repository[]>
|
||||
async list(options?: {
|
||||
state?: Repository['state'];
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}): Promise<Repository[]>;
|
||||
|
||||
async get(id: string): Promise<Repository | null>
|
||||
async get(id: string): Promise<Repository | null>;
|
||||
|
||||
async add(input: AddRepositoryInput): Promise<Repository>
|
||||
async add(input: AddRepositoryInput): Promise<Repository>;
|
||||
|
||||
async update(id: string, input: UpdateRepositoryInput): Promise<Repository>
|
||||
async update(id: string, input: UpdateRepositoryInput): Promise<Repository>;
|
||||
|
||||
async remove(id: string): Promise<void>
|
||||
async remove(id: string): Promise<void>;
|
||||
|
||||
async getStats(id: string): Promise<{
|
||||
totalSnippets: number;
|
||||
totalTokens: number;
|
||||
totalDocuments: number;
|
||||
lastIndexedAt: Date | null;
|
||||
}>
|
||||
async getStats(id: string): Promise<{
|
||||
totalSnippets: number;
|
||||
totalTokens: number;
|
||||
totalDocuments: number;
|
||||
lastIndexedAt: Date | null;
|
||||
}>;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -97,48 +99,52 @@ export class RepositoryService {
|
||||
### `GET /api/v1/libs`
|
||||
|
||||
Query parameters:
|
||||
|
||||
- `state` (optional): filter by state (`pending`, `indexed`, `error`, etc.)
|
||||
- `limit` (optional, default 50): max results
|
||||
- `offset` (optional, default 0): pagination offset
|
||||
|
||||
Response `200`:
|
||||
|
||||
```json
|
||||
{
|
||||
"libraries": [
|
||||
{
|
||||
"id": "/facebook/react",
|
||||
"title": "React",
|
||||
"description": "...",
|
||||
"source": "github",
|
||||
"state": "indexed",
|
||||
"totalSnippets": 1234,
|
||||
"totalTokens": 98000,
|
||||
"trustScore": 8.5,
|
||||
"stars": 228000,
|
||||
"lastIndexedAt": "2026-03-22T10:00:00Z",
|
||||
"versions": ["v18.3.0", "v17.0.2"]
|
||||
}
|
||||
],
|
||||
"total": 12,
|
||||
"limit": 50,
|
||||
"offset": 0
|
||||
"libraries": [
|
||||
{
|
||||
"id": "/facebook/react",
|
||||
"title": "React",
|
||||
"description": "...",
|
||||
"source": "github",
|
||||
"state": "indexed",
|
||||
"totalSnippets": 1234,
|
||||
"totalTokens": 98000,
|
||||
"trustScore": 8.5,
|
||||
"stars": 228000,
|
||||
"lastIndexedAt": "2026-03-22T10:00:00Z",
|
||||
"versions": ["v18.3.0", "v17.0.2"]
|
||||
}
|
||||
],
|
||||
"total": 12,
|
||||
"limit": 50,
|
||||
"offset": 0
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/v1/libs`
|
||||
|
||||
Request body:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": "github",
|
||||
"sourceUrl": "https://github.com/facebook/react",
|
||||
"branch": "main",
|
||||
"githubToken": "ghp_...",
|
||||
"autoIndex": true
|
||||
"source": "github",
|
||||
"sourceUrl": "https://github.com/facebook/react",
|
||||
"branch": "main",
|
||||
"githubToken": "ghp_...",
|
||||
"autoIndex": true
|
||||
}
|
||||
```
|
||||
|
||||
Response `201`:
|
||||
|
||||
```json
|
||||
{
|
||||
"library": { ...Repository },
|
||||
@@ -149,6 +155,7 @@ Response `201`:
|
||||
`autoIndex: true` (default) immediately queues an indexing job.
|
||||
|
||||
Response `409` if repository already exists:
|
||||
|
||||
```json
|
||||
{ "error": "Repository /facebook/react already exists" }
|
||||
```
|
||||
@@ -176,20 +183,22 @@ Response `404`: not found.
|
||||
Triggers a new indexing job. If a job is already running for this repo, returns the existing job.
|
||||
|
||||
Request body (optional):
|
||||
|
||||
```json
|
||||
{ "version": "v18.3.0" }
|
||||
```
|
||||
|
||||
Response `202`:
|
||||
|
||||
```json
|
||||
{
|
||||
"job": {
|
||||
"id": "uuid",
|
||||
"repositoryId": "/facebook/react",
|
||||
"status": "queued",
|
||||
"progress": 0,
|
||||
"createdAt": "2026-03-22T10:00:00Z"
|
||||
}
|
||||
"job": {
|
||||
"id": "uuid",
|
||||
"repositoryId": "/facebook/react",
|
||||
"status": "queued",
|
||||
"progress": 0,
|
||||
"createdAt": "2026-03-22T10:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -198,15 +207,17 @@ Response `202`:
|
||||
## Error Response Shape
|
||||
|
||||
All error responses follow:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Human-readable message",
|
||||
"code": "MACHINE_READABLE_CODE",
|
||||
"details": {}
|
||||
"error": "Human-readable message",
|
||||
"code": "MACHINE_READABLE_CODE",
|
||||
"details": {}
|
||||
}
|
||||
```
|
||||
|
||||
Error codes:
|
||||
|
||||
- `NOT_FOUND`
|
||||
- `ALREADY_EXISTS`
|
||||
- `INVALID_INPUT`
|
||||
@@ -219,23 +230,23 @@ Error codes:
|
||||
|
||||
```typescript
|
||||
function resolveGitHubId(url: string): string {
|
||||
// Parse owner/repo from URL variants:
|
||||
// https://github.com/facebook/react
|
||||
// https://github.com/facebook/react.git
|
||||
// github.com/facebook/react
|
||||
const match = url.match(/github\.com\/([^/]+)\/([^/\s.]+)/);
|
||||
if (!match) throw new Error('Invalid GitHub URL');
|
||||
return `/${match[1]}/${match[2]}`;
|
||||
// Parse owner/repo from URL variants:
|
||||
// https://github.com/facebook/react
|
||||
// https://github.com/facebook/react.git
|
||||
// github.com/facebook/react
|
||||
const match = url.match(/github\.com\/([^/]+)\/([^/\s.]+)/);
|
||||
if (!match) throw new Error('Invalid GitHub URL');
|
||||
return `/${match[1]}/${match[2]}`;
|
||||
}
|
||||
|
||||
function resolveLocalId(path: string, existingIds: string[]): string {
|
||||
const base = slugify(path.split('/').at(-1)!);
|
||||
let id = `/local/${base}`;
|
||||
let counter = 2;
|
||||
while (existingIds.includes(id)) {
|
||||
id = `/local/${base}-${counter++}`;
|
||||
}
|
||||
return id;
|
||||
const base = slugify(path.split('/').at(-1)!);
|
||||
let id = `/local/${base}`;
|
||||
let counter = 2;
|
||||
while (existingIds.includes(id)) {
|
||||
id = `/local/${base}-${counter++}`;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user