update 0.0.6
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@kevisual/project-search",
|
"name": "@kevisual/project-search",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { ProjectStore, ProjectDoc } from "./project-store";
|
|||||||
import { ProjectListener } from "./project-listener/listener";
|
import { ProjectListener } from "./project-listener/listener";
|
||||||
import { EventEmitter } from "eventemitter3";
|
import { EventEmitter } from "eventemitter3";
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
import { CustomError } from "@kevisual/router";
|
import { CustomError } from "@kevisual/router";
|
||||||
|
|
||||||
type Project = {
|
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> {
|
async deleteFile(filepath: string): Promise<boolean> {
|
||||||
if (!fileIsExist(filepath)) {
|
if (!fileIsExist(filepath)) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ export class ProjectSearch {
|
|||||||
async searchFiles(query: string = '', options?: {
|
async searchFiles(query: string = '', options?: {
|
||||||
projectPath?: string;
|
projectPath?: string;
|
||||||
repo?: string;
|
repo?: string;
|
||||||
|
filepath?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
tags?: string | string[];
|
tags?: string | string[];
|
||||||
summary?: string;
|
summary?: string;
|
||||||
@@ -93,6 +94,7 @@ export class ProjectSearch {
|
|||||||
const filter: string[] = [];
|
const filter: string[] = [];
|
||||||
if (options?.projectPath) filter.push(`projectPath = "${options.projectPath}"`);
|
if (options?.projectPath) filter.push(`projectPath = "${options.projectPath}"`);
|
||||||
if (options?.repo) filter.push(`repo = "${options.repo}"`);
|
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?.title) filter.push(`title = "${options.title}"`);
|
||||||
if (options?.tags) {
|
if (options?.tags) {
|
||||||
const tags = Array.isArray(options.tags) ? options.tags : [options.tags];
|
const tags = Array.isArray(options.tags) ? options.tags : [options.tags];
|
||||||
|
|||||||
@@ -23,6 +23,39 @@ app.route({
|
|||||||
}
|
}
|
||||||
}).addTo(app);
|
}).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)
|
* 更新文件自定义信息(title/tags/summary/description/link)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ app
|
|||||||
args: {
|
args: {
|
||||||
q: z.string().optional().describe('搜索关键词,选填;留空或不传则返回全部文件'),
|
q: z.string().optional().describe('搜索关键词,选填;留空或不传则返回全部文件'),
|
||||||
projectPath: z.string().optional().describe('按项目根目录路径过滤,仅返回该项目下的文件,选填'),
|
projectPath: z.string().optional().describe('按项目根目录路径过滤,仅返回该项目下的文件,选填'),
|
||||||
|
filepath: z.string().optional().describe('按文件绝对路径过滤,选填'),
|
||||||
repo: z.string().optional().describe('按代码仓库标识过滤(如 owner/repo),选填'),
|
repo: z.string().optional().describe('按代码仓库标识过滤(如 owner/repo),选填'),
|
||||||
title: z.string().optional().describe('按人工标注的标题字段过滤,选填'),
|
title: z.string().optional().describe('按人工标注的标题字段过滤,选填'),
|
||||||
tags: z.array(z.string()).optional().describe('按人工标注的标签列表过滤,选填'),
|
tags: z.array(z.string()).optional().describe('按人工标注的标签列表过滤,选填'),
|
||||||
@@ -27,13 +28,13 @@ app
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.define(async (ctx) => {
|
.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) {
|
if (!q) {
|
||||||
sort = sort ?? ['projectPath:asc'];
|
sort = sort ?? ['projectPath:asc'];
|
||||||
limit = limit ?? 1000;
|
limit = limit ?? 1000;
|
||||||
}
|
}
|
||||||
const projectSearch = manager.projectSearch;
|
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 };
|
ctx.body = { list: hits };
|
||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
|
|||||||
Reference in New Issue
Block a user