update 0.0.6
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kevisual/project-search",
|
||||
"version": "0.0.5",
|
||||
"version": "0.0.6",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { ProjectStore, ProjectDoc } from "./project-store";
|
||||
import { ProjectListener } from "./project-listener/listener";
|
||||
import { EventEmitter } from "eventemitter3";
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { CustomError } from "@kevisual/router";
|
||||
|
||||
type Project = {
|
||||
@@ -171,6 +172,21 @@ export class ProjectManager implements ProjectManagerInterface {
|
||||
}
|
||||
}
|
||||
|
||||
async writeFile(filepath: string, content: string): Promise<boolean> {
|
||||
try {
|
||||
const buffer = Buffer.from(content, 'base64');
|
||||
const dir = path.dirname(filepath);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
fs.writeFileSync(filepath, buffer);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('写入文件失败:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async deleteFile(filepath: string): Promise<boolean> {
|
||||
if (!fileIsExist(filepath)) {
|
||||
return false;
|
||||
|
||||
@@ -78,6 +78,7 @@ export class ProjectSearch {
|
||||
async searchFiles(query: string = '', options?: {
|
||||
projectPath?: string;
|
||||
repo?: string;
|
||||
filepath?: string;
|
||||
title?: string;
|
||||
tags?: string | string[];
|
||||
summary?: string;
|
||||
@@ -93,6 +94,7 @@ export class ProjectSearch {
|
||||
const filter: string[] = [];
|
||||
if (options?.projectPath) filter.push(`projectPath = "${options.projectPath}"`);
|
||||
if (options?.repo) filter.push(`repo = "${options.repo}"`);
|
||||
if (options?.filepath) filter.push(`filepath = "${options.filepath}"`);
|
||||
if (options?.title) filter.push(`title = "${options.title}"`);
|
||||
if (options?.tags) {
|
||||
const tags = Array.isArray(options.tags) ? options.tags : [options.tags];
|
||||
|
||||
@@ -23,6 +23,39 @@ app.route({
|
||||
}
|
||||
}).addTo(app);
|
||||
|
||||
/**
|
||||
* 更新文件内容(base64 编码)
|
||||
*/
|
||||
app.route({
|
||||
path: 'project-file',
|
||||
key: 'update-content',
|
||||
middleware: ['auth-admin'],
|
||||
description: '将 base64 编码的内容写入指定文件路径,用于更新或创建文件',
|
||||
metadata: {
|
||||
args: {
|
||||
filepath: z.string().nonempty().describe('要写入的文件绝对路径,必填'),
|
||||
content: z.string().nonempty().describe('文件内容的 base64 编码,必填'),
|
||||
}
|
||||
}
|
||||
}).define(async (ctx) => {
|
||||
const { filepath, content } = ctx.query as {
|
||||
filepath: string;
|
||||
content: string;
|
||||
};
|
||||
if (!filepath) ctx.throw(400, 'filepath 不能为空');
|
||||
if (!content) ctx.throw(400, 'content 不能为空');
|
||||
|
||||
try {
|
||||
const success = await manager.writeFile(filepath, content);
|
||||
if (!success) {
|
||||
ctx.throw(500, '写入文件失败');
|
||||
}
|
||||
ctx.body = { success: true };
|
||||
} catch (error) {
|
||||
ctx.throw(500, '写入文件失败');
|
||||
}
|
||||
}).addTo(app);
|
||||
|
||||
/**
|
||||
* 更新文件自定义信息(title/tags/summary/description/link)
|
||||
*/
|
||||
|
||||
@@ -14,6 +14,7 @@ app
|
||||
args: {
|
||||
q: z.string().optional().describe('搜索关键词,选填;留空或不传则返回全部文件'),
|
||||
projectPath: z.string().optional().describe('按项目根目录路径过滤,仅返回该项目下的文件,选填'),
|
||||
filepath: z.string().optional().describe('按文件绝对路径过滤,选填'),
|
||||
repo: z.string().optional().describe('按代码仓库标识过滤(如 owner/repo),选填'),
|
||||
title: z.string().optional().describe('按人工标注的标题字段过滤,选填'),
|
||||
tags: z.array(z.string()).optional().describe('按人工标注的标签列表过滤,选填'),
|
||||
@@ -27,13 +28,13 @@ app
|
||||
}
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
let { q, projectPath, repo, title, tags, summary, description, link, sort, limit, getContent = false } = ctx.query as { q?: string; projectPath?: string; repo?: string; title?: string; tags?: string[]; summary?: string; description?: string; link?: string; sort?: string[]; limit?: number; getContent?: boolean };
|
||||
let { q, projectPath, filepath, repo, title, tags, summary, description, link, sort, limit, getContent = false } = ctx.query as { q?: string; projectPath?: string; filepath?: string; repo?: string; title?: string; tags?: string[]; summary?: string; description?: string; link?: string; sort?: string[]; limit?: number; getContent?: boolean };
|
||||
if (!q) {
|
||||
sort = sort ?? ['projectPath:asc'];
|
||||
limit = limit ?? 1000;
|
||||
}
|
||||
const projectSearch = manager.projectSearch;
|
||||
const hits = await projectSearch.searchFiles(q, { projectPath, repo, title, tags, summary, description, link, sort, limit, getContent });
|
||||
const hits = await projectSearch.searchFiles(q, { projectPath, filepath, repo, title, tags, summary, description, link, sort, limit, getContent });
|
||||
ctx.body = { list: hits };
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
Reference in New Issue
Block a user