@whispering233/ai-editor-server 0.0.47 → 0.0.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/client-dist/assets/index-CP2R5sxP.js +621 -0
  2. package/client-dist/assets/index-Do0muC_e.css +1 -0
  3. package/client-dist/assets/module-RjUF93sV.js +716 -0
  4. package/client-dist/assets/native-48B9X9Wg.js +1 -0
  5. package/client-dist/index.html +2 -2
  6. package/dist/backup.d.ts +14 -11
  7. package/dist/backup.d.ts.map +1 -1
  8. package/dist/backup.js +40 -23
  9. package/dist/backup.js.map +1 -1
  10. package/dist/cloud/state.d.ts +18 -1
  11. package/dist/cloud/state.d.ts.map +1 -1
  12. package/dist/cloud/state.js +34 -3
  13. package/dist/cloud/state.js.map +1 -1
  14. package/dist/cloud/sync.d.ts +3 -3
  15. package/dist/cloud/sync.d.ts.map +1 -1
  16. package/dist/cloud/sync.js +4 -4
  17. package/dist/cloud/sync.js.map +1 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/routes/chat.d.ts +4 -0
  22. package/dist/routes/chat.d.ts.map +1 -1
  23. package/dist/routes/chat.js +16 -2
  24. package/dist/routes/chat.js.map +1 -1
  25. package/dist/routes/cloud.js +1 -1
  26. package/dist/routes/cloud.js.map +1 -1
  27. package/dist/routes/entity.d.ts +1 -1
  28. package/dist/routes/entity.d.ts.map +1 -1
  29. package/dist/routes/entity.js +110 -90
  30. package/dist/routes/entity.js.map +1 -1
  31. package/dist/routes/manuscript.d.ts +4 -0
  32. package/dist/routes/manuscript.d.ts.map +1 -0
  33. package/dist/routes/manuscript.js +86 -0
  34. package/dist/routes/manuscript.js.map +1 -0
  35. package/dist/routes/outline.d.ts +5 -1
  36. package/dist/routes/outline.d.ts.map +1 -1
  37. package/dist/routes/outline.js +30 -3
  38. package/dist/routes/outline.js.map +1 -1
  39. package/dist/routes/trash.d.ts.map +1 -1
  40. package/dist/routes/trash.js +14 -26
  41. package/dist/routes/trash.js.map +1 -1
  42. package/package.json +5 -5
  43. package/client-dist/assets/index-DAzWamd7.css +0 -1
  44. package/client-dist/assets/index-DyrUkODP.js +0 -523
  45. package/dist/reference-files.d.ts +0 -87
  46. package/dist/reference-files.d.ts.map +0 -1
  47. package/dist/reference-files.js +0 -266
  48. package/dist/reference-files.js.map +0 -1
  49. package/dist/routes/reference.d.ts +0 -4
  50. package/dist/routes/reference.d.ts.map +0 -1
  51. package/dist/routes/reference.js +0 -23
  52. package/dist/routes/reference.js.map +0 -1
@@ -1,87 +0,0 @@
1
- import { type Db } from "@whispering233/ai-editor-db";
2
- import type { EntityRow } from "@whispering233/ai-editor-shared";
3
- /** 参考资料目录(项目根下,书籍项目文件夹自包含参考资料) */
4
- export declare const REFERENCE_DIR = "references";
5
- /** 软删回收目录(references/.trash/,软删文件移入,restore 移回、purge 物理删) */
6
- export declare const REFERENCE_TRASH_DIR = ".trash";
7
- /** 文件 mtime 比对容差(毫秒):**仅防御 ISO 毫秒截断 roundtrip**(mtimeMs 浮点 → toISOString
8
- * 毫秒截断 → getTime 可能差亚毫秒)。与备份体系 1s 容差语义相反——备份容差防「mtime 未刷新
9
- * 误判有变更」,scan 容差过大会**漏检真实外部修改**(1s 内的改动检测不到),故取最小值。
10
- * 应用内写入:writeFileAtomic 后 stat 与 scan 读取的 mtime 必然一致(同一文件),严格相等即可。*/
11
- export declare const REFERENCE_MTIME_TOLERANCE_MS = 2;
12
- /** 原子写(同款:临时文件 + fsync + rename;参考资料 md 文件同样禁止直接覆盖) */
13
- export declare function writeFileAtomic(filePath: string, data: string): void;
14
- /** 确保 references/ 与 references/.trash/ 存在(幂等) */
15
- export declare function ensureReferenceDirs(root: string): void;
16
- /** 生成不冲突文件名:`<base>.md` 已存在 → `<base> (N).md`(N 最小正整数,沿用「书名 (N)」先例) */
17
- export declare function uniqueFileNameIn(dir: string, base: string): string;
18
- /** 写参考文件(frontmatter + 正文,原子写);返回 { fileName(调用方已唯一化), mtime(ISO) } */
19
- export declare function writeReferenceFile(root: string, fileName: string, meta: {
20
- title: string;
21
- category: string;
22
- tags: string[];
23
- extraLines?: readonly string[];
24
- }, body: string): {
25
- fileName: string;
26
- mtime: string;
27
- };
28
- /** 解析后的参考文件(meta + body + mtime) */
29
- export interface ParsedReferenceFile {
30
- title: string | undefined;
31
- category: string | undefined;
32
- tags: string[];
33
- body: string;
34
- /** 未知 frontmatter 行(外部编辑器自定义字段,序列化时原样保留) */
35
- extraLines: string[];
36
- /** 文件 mtime(ISO,毫秒精度) */
37
- mtime: string;
38
- /** mtime 毫秒数值(scan 容差比对用) */
39
- mtimeMs: number;
40
- }
41
- /** 读参考文件并解析 frontmatter;文件缺失 → null */
42
- export declare function readReferenceFile(root: string, fileName: string): ParsedReferenceFile | null;
43
- /** 软删移动:references/<fileName> → references/.trash/<唯一名>;返回实际文件名(冲突递增) */
44
- export declare function moveReferenceToTrash(root: string, fileName: string): string;
45
- /** 还原移动:references/.trash/<fileName> → references/<唯一名>;返回实际文件名(冲突递增);
46
- * .trash/ 下文件缺失 → 返回 null(外部已清理——仅还原索引,详情读取时 409 REFERENCE_FILE_MISSING) */
47
- export declare function restoreReferenceFromTrash(root: string, fileName: string): string | null;
48
- /** 物理删参考文件(references/ 与 references/.trash/ 都尝试;缺失忽略——幂等) */
49
- export declare function removeReferenceFile(root: string, fileName: string): void;
50
- /** references/ 顶层 md 文件列表(排除 .trash/;不含子目录——YAGNI) */
51
- export declare function listReferenceFiles(root: string): string[];
52
- /** 扫描结果统计(幂等全量比对) */
53
- export interface ScanReferenceResult {
54
- added: number;
55
- updated: number;
56
- restored: number;
57
- removed: number;
58
- skipped: number;
59
- errors: string[];
60
- }
61
- /** 只读统计:references/ 下未同步文件数(无匹配索引 或 mtime 不一致;**无副作用**——
62
- * 列表页打开项目提示条用,不触发索引写入/软删) */
63
- export declare function countUnsyncedReferenceFiles(root: string, db: Db): number;
64
- /**
65
- * 扫描重建参考资料索引(POST /api/v1/reference/scan)。
66
- * 规则(2026-08 修订:软删文件归 .trash/,references/ 下缺失即视为外部删除):
67
- * 1. 遍历 references/ 顶层 *.md(排除 .trash/):
68
- * - 非软删索引匹配(kind='file' 且 file_name === 文件名)→ mtime 一致(容差内)跳过;
69
- * 不一致 → 以文件为准更新(title/category/tags/content/file_mtime/updated_at)
70
- * - 软删索引匹配 → 还原(deleted_at=NULL,文件留 references/ 原地)+ 更新数据
71
- * - 无匹配 → 新建(title=frontmatter title ?? 文件名去扩展名、category ?? material)
72
- * 2. 反向:非软删 file 类索引,references/ 下对应文件缺失 → 索引同步软删(进回收站可还原)
73
- * 幂等:重复执行无副作用;只处理顶层文件。
74
- */
75
- export declare function scanReferences(root: string, db: Db): ScanReferenceResult;
76
- /** 读取实体的 reference data(不存在 → null;**含软删**——trash restore/purge 分支用,
77
- * getEntity 过滤 deleted_at 读不到软删实体);用于 route 层 kind 分支判定 */
78
- export declare function getReferenceRowAny(db: Db, id: string): {
79
- row: EntityRow;
80
- data: Record<string, unknown>;
81
- } | null;
82
- /** 读取实体的 reference data(不存在/已软删 → null;用于 route 层 kind 分支判定) */
83
- export declare function getReferenceRow(db: Db, id: string): {
84
- row: EntityRow;
85
- data: Record<string, unknown>;
86
- } | null;
87
- //# sourceMappingURL=reference-files.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reference-files.d.ts","sourceRoot":"","sources":["../src/reference-files.ts"],"names":[],"mappings":"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"}
@@ -1,266 +0,0 @@
1
- // 参考资料文件服务
2
- //
3
- // 职责:references/ 目录(项目文件夹内自包含)的读写/原子写/移动(软删 .trash/)/物理删,
4
- // + 扫描重建索引(文件 = 真相源,DB 索引 = 派生镜像,mtime 快照比对)。
5
- // 同步方案(与用户确认):
6
- // - 应用内编辑:先原子写文件再更新 DB(文件写失败 → 操作报错 DB 不动;DB 失败 → 文件已写,
7
- // scan 以文件为准自愈——文件可重建 DB 而 DB 不可重建文件)
8
- // - 外部编辑/新增/删除:scan 幂等全量比对——「已索引跳过」= 索引存在 且 文件 mtime === 索引
9
- // file_mtime;mtime 不一致 → 以文件为准重新解析 frontmatter + 正文更新索引
10
- // - 软删:文件移 references/.trash/ + 索引 deleted_at;restore 移回;purge 物理删
11
- // 依赖方向:本模块只依赖 shared 纯函数与 db 包实体查询(getEntity/updateEntity/softDeleteEntity/
12
- // restoreEntity——scan 用),不依赖 route/middleware(避免循环依赖)。
13
- import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, openSync, fsyncSync, closeSync } from "node:fs";
14
- import { join } from "node:path";
15
- import { parseReferenceFrontmatter, serializeReferenceFile, } from "@whispering233/ai-editor-shared";
16
- import { createEntity, getEntity, nowIso, restoreEntity, softDeleteEntity, updateEntity, } from "@whispering233/ai-editor-db";
17
- /** 参考资料目录(项目根下,书籍项目文件夹自包含参考资料) */
18
- export const REFERENCE_DIR = "references";
19
- /** 软删回收目录(references/.trash/,软删文件移入,restore 移回、purge 物理删) */
20
- export const REFERENCE_TRASH_DIR = ".trash";
21
- /** 文件 mtime 比对容差(毫秒):**仅防御 ISO 毫秒截断 roundtrip**(mtimeMs 浮点 → toISOString
22
- * 毫秒截断 → getTime 可能差亚毫秒)。与备份体系 1s 容差语义相反——备份容差防「mtime 未刷新
23
- * 误判有变更」,scan 容差过大会**漏检真实外部修改**(1s 内的改动检测不到),故取最小值。
24
- * 应用内写入:writeFileAtomic 后 stat 与 scan 读取的 mtime 必然一致(同一文件),严格相等即可。*/
25
- export const REFERENCE_MTIME_TOLERANCE_MS = 2;
26
- /** 原子写(同款:临时文件 + fsync + rename;参考资料 md 文件同样禁止直接覆盖) */
27
- export function writeFileAtomic(filePath, data) {
28
- const tmp = `${filePath}.tmp`;
29
- const fd = openSync(tmp, "w");
30
- try {
31
- writeFileSync(fd, data, "utf8");
32
- fsyncSync(fd);
33
- }
34
- finally {
35
- closeSync(fd);
36
- }
37
- renameSync(tmp, filePath);
38
- }
39
- /** 确保 references/ 与 references/.trash/ 存在(幂等) */
40
- export function ensureReferenceDirs(root) {
41
- mkdirSync(join(root, REFERENCE_DIR), { recursive: true });
42
- mkdirSync(join(root, REFERENCE_DIR, REFERENCE_TRASH_DIR), { recursive: true });
43
- }
44
- /** 生成不冲突文件名:`<base>.md` 已存在 → `<base> (N).md`(N 最小正整数,沿用「书名 (N)」先例) */
45
- export function uniqueFileNameIn(dir, base) {
46
- let name = `${base}.md`;
47
- let n = 2;
48
- while (existsSync(join(dir, name))) {
49
- name = `${base} (${n}).md`;
50
- n += 1;
51
- }
52
- return name;
53
- }
54
- /** 写参考文件(frontmatter + 正文,原子写);返回 { fileName(调用方已唯一化), mtime(ISO) } */
55
- export function writeReferenceFile(root, fileName, meta, body) {
56
- ensureReferenceDirs(root);
57
- writeFileAtomic(join(root, REFERENCE_DIR, fileName), serializeReferenceFile({ ...meta, body }));
58
- return { fileName, mtime: new Date(statSync(join(root, REFERENCE_DIR, fileName)).mtimeMs).toISOString() };
59
- }
60
- /** 读参考文件并解析 frontmatter;文件缺失 → null */
61
- export function readReferenceFile(root, fileName) {
62
- const full = join(root, REFERENCE_DIR, fileName);
63
- if (!existsSync(full))
64
- return null;
65
- const text = readFileSync(full, "utf8");
66
- const parsed = parseReferenceFrontmatter(text);
67
- const st = statSync(full);
68
- return {
69
- title: parsed.title,
70
- category: parsed.category,
71
- tags: parsed.tags,
72
- body: parsed.body,
73
- extraLines: parsed.extraLines,
74
- mtime: new Date(st.mtimeMs).toISOString(),
75
- mtimeMs: st.mtimeMs,
76
- };
77
- }
78
- /** 软删移动:references/<fileName> → references/.trash/<唯一名>;返回实际文件名(冲突递增) */
79
- export function moveReferenceToTrash(root, fileName) {
80
- ensureReferenceDirs(root);
81
- const trashDir = join(root, REFERENCE_DIR, REFERENCE_TRASH_DIR);
82
- const base = fileName.replace(/\.md$/, "");
83
- const target = uniqueFileNameIn(trashDir, base);
84
- renameSync(join(root, REFERENCE_DIR, fileName), join(trashDir, target));
85
- return target;
86
- }
87
- /** 还原移动:references/.trash/<fileName> → references/<唯一名>;返回实际文件名(冲突递增);
88
- * .trash/ 下文件缺失 → 返回 null(外部已清理——仅还原索引,详情读取时 409 REFERENCE_FILE_MISSING) */
89
- export function restoreReferenceFromTrash(root, fileName) {
90
- ensureReferenceDirs(root);
91
- const trashFile = join(root, REFERENCE_DIR, REFERENCE_TRASH_DIR, fileName);
92
- if (!existsSync(trashFile))
93
- return null;
94
- const base = fileName.replace(/\.md$/, "");
95
- const target = uniqueFileNameIn(join(root, REFERENCE_DIR), base);
96
- renameSync(trashFile, join(root, REFERENCE_DIR, target));
97
- return target;
98
- }
99
- /** 物理删参考文件(references/ 与 references/.trash/ 都尝试;缺失忽略——幂等) */
100
- export function removeReferenceFile(root, fileName) {
101
- for (const dir of [REFERENCE_DIR, join(REFERENCE_DIR, REFERENCE_TRASH_DIR)]) {
102
- const full = join(root, dir, fileName);
103
- if (existsSync(full))
104
- rmSync(full);
105
- }
106
- }
107
- /** references/ 顶层 md 文件列表(排除 .trash/;不含子目录——YAGNI) */
108
- export function listReferenceFiles(root) {
109
- const dir = join(root, REFERENCE_DIR);
110
- if (!existsSync(dir))
111
- return [];
112
- return readdirSync(dir, { withFileTypes: true })
113
- .filter((e) => e.isFile() && e.name.endsWith(".md"))
114
- .map((e) => e.name)
115
- .sort();
116
- }
117
- /** 实体行 → reference data 解析(data 坏 JSON 防御由 rowToEntityRow 兜底) */
118
- function referenceDataOf(row) {
119
- return (row.data ?? {});
120
- }
121
- /** file 类索引读取(live/softDeleted 双 Map,scan 与只读统计共用) */
122
- function readReferenceIndexes(db) {
123
- const rows = db
124
- .prepare("SELECT id, name, data, deleted_at FROM entities WHERE type = 'reference'")
125
- .all();
126
- const live = new Map();
127
- const softDeleted = new Map();
128
- for (const r of rows) {
129
- let data;
130
- try {
131
- data = JSON.parse(r.data);
132
- }
133
- catch {
134
- continue; // 坏行防御(rowToEntityRow 同款语义,跳过不阻塞)
135
- }
136
- if (data.kind !== "file" || typeof data.file_name !== "string")
137
- continue;
138
- if (r.deleted_at === null)
139
- live.set(data.file_name, { id: r.id, name: r.name, data });
140
- else
141
- softDeleted.set(data.file_name, { id: r.id, name: r.name, data });
142
- }
143
- return { live, softDeleted };
144
- }
145
- /** 只读统计:references/ 下未同步文件数(无匹配索引 或 mtime 不一致;**无副作用**——
146
- * 列表页打开项目提示条用,不触发索引写入/软删) */
147
- export function countUnsyncedReferenceFiles(root, db) {
148
- ensureReferenceDirs(root);
149
- const { live } = readReferenceIndexes(db);
150
- let unsynced = 0;
151
- for (const fileName of listReferenceFiles(root)) {
152
- const file = readReferenceFile(root, fileName);
153
- if (file === null)
154
- continue;
155
- const index = live.get(fileName);
156
- if (index === undefined) {
157
- unsynced += 1; // 无索引(本地新增)
158
- continue;
159
- }
160
- const stored = typeof index.data.file_mtime === "string" ? new Date(index.data.file_mtime).getTime() : NaN;
161
- if (Number.isNaN(stored) || Math.abs(file.mtimeMs - stored) > REFERENCE_MTIME_TOLERANCE_MS) {
162
- unsynced += 1; // mtime 不一致(外部修改)
163
- }
164
- }
165
- return unsynced;
166
- }
167
- /**
168
- * 扫描重建参考资料索引(POST /api/v1/reference/scan)。
169
- * 规则(2026-08 修订:软删文件归 .trash/,references/ 下缺失即视为外部删除):
170
- * 1. 遍历 references/ 顶层 *.md(排除 .trash/):
171
- * - 非软删索引匹配(kind='file' 且 file_name === 文件名)→ mtime 一致(容差内)跳过;
172
- * 不一致 → 以文件为准更新(title/category/tags/content/file_mtime/updated_at)
173
- * - 软删索引匹配 → 还原(deleted_at=NULL,文件留 references/ 原地)+ 更新数据
174
- * - 无匹配 → 新建(title=frontmatter title ?? 文件名去扩展名、category ?? material)
175
- * 2. 反向:非软删 file 类索引,references/ 下对应文件缺失 → 索引同步软删(进回收站可还原)
176
- * 幂等:重复执行无副作用;只处理顶层文件。
177
- */
178
- export function scanReferences(root, db) {
179
- const result = { added: 0, updated: 0, restored: 0, removed: 0, skipped: 0, errors: [] };
180
- ensureReferenceDirs(root);
181
- // 现有 file 类索引(含软删——还原判定用)
182
- const { live: liveIndex, softDeleted: softDeletedIndex } = readReferenceIndexes(db);
183
- // 1. 正向:文件 → 索引
184
- for (const fileName of listReferenceFiles(root)) {
185
- const file = readReferenceFile(root, fileName);
186
- if (file === null)
187
- continue; // 竞态(读取间被删)→ 下一轮 scan 处理
188
- const live = liveIndex.get(fileName);
189
- if (live !== undefined) {
190
- // mtime 容差比对:一致跳过
191
- const stored = typeof live.data.file_mtime === "string" ? new Date(live.data.file_mtime).getTime() : NaN;
192
- if (!Number.isNaN(stored) && Math.abs(file.mtimeMs - stored) <= REFERENCE_MTIME_TOLERANCE_MS) {
193
- result.skipped += 1;
194
- continue;
195
- }
196
- applyFileToIndex(db, live.id, file, fileName);
197
- result.updated += 1;
198
- continue;
199
- }
200
- const soft = softDeletedIndex.get(fileName);
201
- if (soft !== undefined) {
202
- // 软删索引 + 文件回归 references/ → 还原 + 更新
203
- restoreEntity(db, "reference", soft.id);
204
- applyFileToIndex(db, soft.id, file, fileName);
205
- result.restored += 1;
206
- continue;
207
- }
208
- // 无匹配 → 新建(title/category 兜底)
209
- const title = file.title ?? fileName.replace(/\.md$/, "");
210
- const category = file.category ?? "material";
211
- const data = {
212
- kind: "file",
213
- file_name: fileName,
214
- file_mtime: file.mtime,
215
- type: category,
216
- content: file.body,
217
- ...(file.tags.length > 0 ? { tags: file.tags } : {}),
218
- };
219
- createEntity(db, { type: "reference", name: title, data });
220
- result.added += 1;
221
- }
222
- // 2. 反向:非软删 file 类索引,references/ 下文件缺失 → 软删
223
- const files = new Set(listReferenceFiles(root));
224
- for (const [fileName, live] of liveIndex) {
225
- if (!files.has(fileName)) {
226
- softDeleteEntity(db, live.id, nowIso());
227
- result.removed += 1;
228
- }
229
- }
230
- return result;
231
- }
232
- /** 以文件为准更新索引(name + data 浅合并:title/category/tags/content/file_mtime) */
233
- function applyFileToIndex(db, id, file, fileName) {
234
- updateEntity(db, id, {
235
- name: file.title ?? fileName.replace(/\.md$/, ""),
236
- data: {
237
- type: file.category ?? "material",
238
- content: file.body,
239
- file_mtime: file.mtime,
240
- ...(file.tags.length > 0 ? { tags: file.tags } : {}),
241
- },
242
- });
243
- }
244
- /** 读取实体的 reference data(不存在 → null;**含软删**——trash restore/purge 分支用,
245
- * getEntity 过滤 deleted_at 读不到软删实体);用于 route 层 kind 分支判定 */
246
- export function getReferenceRowAny(db, id) {
247
- const raw = db.prepare("SELECT * FROM entities WHERE id = ?").get(id);
248
- if (raw === undefined)
249
- return null;
250
- let data;
251
- try {
252
- data = JSON.parse(typeof raw.data === "string" ? raw.data : "{}");
253
- }
254
- catch {
255
- data = {};
256
- }
257
- return { row: raw, data };
258
- }
259
- /** 读取实体的 reference data(不存在/已软删 → null;用于 route 层 kind 分支判定) */
260
- export function getReferenceRow(db, id) {
261
- const row = getEntity(db, id);
262
- if (row === null)
263
- return null;
264
- return { row, data: referenceDataOf(row) };
265
- }
266
- //# sourceMappingURL=reference-files.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reference-files.js","sourceRoot":"","sources":["../src/reference-files.ts"],"names":[],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- import { Hono } from "hono";
2
- /** 参考资料路由(挂载于 /api/v1/reference,index.ts) */
3
- export declare const referenceRoutes: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
4
- //# sourceMappingURL=reference.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../src/routes/reference.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,6CAA6C;AAC7C,eAAO,MAAM,eAAe,4EAAa,CAAC"}
@@ -1,23 +0,0 @@
1
- // 参考资料专属路由:扫描重建索引端点
2
- //
3
- // DB 索引 = 派生镜像;mtime 快照比对幂等全量)。实体 CRUD 走泛型 /api/v1/entity/reference
4
- // (文件联动在 routes/entity.ts + routes/trash.ts 内部完成),本路由只承载参考资料专属端点。
5
- import { Hono } from "hono";
6
- import { ok } from "../middleware/error.js";
7
- import { requireCurrentProject } from "../middleware/project.js";
8
- import { countUnsyncedReferenceFiles, scanReferences } from "../reference-files.js";
9
- /** 参考资料路由(挂载于 /api/v1/reference,index.ts) */
10
- export const referenceRoutes = new Hono();
11
- // POST /api/v1/reference/scan —— 扫描重建索引(幂等全量比对;返回统计)
12
- // 无项目 → 409 NO_PROJECT_OPEN(requireCurrentProject);失败不抛错——errors 数组带回(解析容错)
13
- referenceRoutes.post("/scan", (c) => {
14
- const project = requireCurrentProject();
15
- return c.json(ok(scanReferences(project.root, project.db)));
16
- });
17
- // GET /api/v1/reference/scan/status —— 只读探测:references/ 下未同步文件数(无副作用)
18
- // 列表页打开项目提示条用(「检测到 N 个未同步的本地文档」);扫描按钮执行后应为 0
19
- referenceRoutes.get("/scan/status", (c) => {
20
- const project = requireCurrentProject();
21
- return c.json(ok({ unsynced: countUnsyncedReferenceFiles(project.root, project.db) }));
22
- });
23
- //# sourceMappingURL=reference.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reference.js","sourceRoot":"","sources":["../../src/routes/reference.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,EAAE;AACF,oEAAoE;AACpE,kEAAkE;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEpF,6CAA6C;AAC7C,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,IAAI,EAAE,CAAC;AAE1C,qDAAqD;AACrD,4EAA4E;AAC5E,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;IAClC,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAC;IACxC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC,CAAC,CAAC;AAEH,sEAAsE;AACtE,6CAA6C;AAC7C,eAAe,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE;IACxC,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAC;IACxC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,2BAA2B,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACzF,CAAC,CAAC,CAAC"}