skill-home 0.2.0 → 0.3.0

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 (41) hide show
  1. package/SKILL.md +17 -17
  2. package/dist/cli/cmd_read.js +93 -26
  3. package/dist/cli/cmd_read.js.map +1 -1
  4. package/dist/cli/config.d.ts +16 -0
  5. package/dist/cli/config.d.ts.map +1 -0
  6. package/dist/cli/config.js +84 -0
  7. package/dist/cli/config.js.map +1 -0
  8. package/dist/cli/health.d.ts +7 -0
  9. package/dist/cli/health.d.ts.map +1 -0
  10. package/dist/cli/health.js +32 -0
  11. package/dist/cli/health.js.map +1 -0
  12. package/dist/config.d.ts +44 -0
  13. package/dist/config.d.ts.map +1 -0
  14. package/dist/config.js +65 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/fetch/archive.d.ts +13 -0
  17. package/dist/fetch/archive.d.ts.map +1 -0
  18. package/dist/fetch/archive.js +115 -0
  19. package/dist/fetch/archive.js.map +1 -0
  20. package/dist/fetch/backup.d.ts +77 -0
  21. package/dist/fetch/backup.d.ts.map +1 -0
  22. package/dist/fetch/backup.js +292 -0
  23. package/dist/fetch/backup.js.map +1 -0
  24. package/dist/fetch/index.d.ts +2 -1
  25. package/dist/fetch/index.d.ts.map +1 -1
  26. package/dist/fetch/index.js +3 -1
  27. package/dist/fetch/index.js.map +1 -1
  28. package/dist/fetch/paths.d.ts +5 -3
  29. package/dist/fetch/paths.d.ts.map +1 -1
  30. package/dist/fetch/paths.js +19 -24
  31. package/dist/fetch/paths.js.map +1 -1
  32. package/dist/health.d.ts +41 -0
  33. package/dist/health.d.ts.map +1 -0
  34. package/dist/health.js +507 -0
  35. package/dist/health.js.map +1 -0
  36. package/dist/help/helpFile.d.ts +1 -1
  37. package/dist/help/manifest.d.ts +7 -19
  38. package/dist/help/manifest.d.ts.map +1 -1
  39. package/dist/help/manifest.js +22 -7
  40. package/dist/help/manifest.js.map +1 -1
  41. package/package.json +2 -2
@@ -0,0 +1,292 @@
1
+ // 备份导出/导入恢复:HELP SM8-3「备份与导出(数据资产)」+ SM8-4「导入与恢复(迁移)」的落点。
2
+ //
3
+ // 与老家的关系(`docs/plugins/plugin-home-ilife/t707-备份取舍.md` 有完整对账):形状照 `ops.py` 那套
4
+ // (`backups/` 同库目录、`home_backup_<时间戳>.zip`、保留 N 份、覆盖前二次备份),但有三处**有意不同**:
5
+ // 1. **不做照片**:本包 src 零读 `HOME_PHOTOS_DIR`(`docs/env.md:12` 已登记的实况),故 zip 只装库 + 清单;
6
+ // 2. **快照用 `VACUUM INTO`**:老家直接 `zf.write(DB_PATH)`,而本包库开 WAL(`db.ts:66`),
7
+ // 照抄会把未落主库的 WAL 内容漏掉——`VACUUM INTO` 出的是包含 WAL 的一致快照;
8
+ // 3. **不做 JSON 导入**:SM8-4 的「冲突预览 → 跳过/合并/覆盖」是老家的物品级合并,本票只做
9
+ // **整库恢复**(`import` 收 `.zip` 备份),物品级合并留作后续票(见该文档「遗留」)。
10
+ // 三条都在票面「留给执行者判断取舍」的范围内,理由与代价写在上面的文档里。
11
+ import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
12
+ import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
13
+ import { closeHomeDb, openHomeDb } from './db.js';
14
+ import { HomeFetchError, HomePolicyError } from './errors.js';
15
+ import { dbFilename, resolveDbDir, resolveDbPath } from './paths.js';
16
+ import { loadHomeConfig } from '../config.js';
17
+ import { zipRead, zipWrite } from './archive.js';
18
+ /** 备份目录名的默认值:=改造前的代码常量 `BACKUP_DIR_NAME`(配置项 `backup.dir` 空串即用它)。 */
19
+ export const DEFAULT_BACKUP_DIR_NAME = 'backups'; // 老家 ops.py:26 同值
20
+ const BACKUP_KEEP_N = 5; // 老家 ops.py:25 同值
21
+ const BACKUP_PREFIX = 'home_backup_';
22
+ const EXPORT_SCHEMA_VERSION = 1;
23
+ function p2(n, w = 2) { return String(n).padStart(w, '0'); }
24
+ function stamp(d = new Date()) {
25
+ return p2(d.getFullYear(), 4) + p2(d.getMonth() + 1) + p2(d.getDate()) + '_' +
26
+ p2(d.getHours()) + p2(d.getMinutes()) + p2(d.getSeconds()) + '_' + p2(d.getMilliseconds(), 3);
27
+ }
28
+ function nowStr(d = new Date()) {
29
+ return p2(d.getFullYear(), 4) + '-' + p2(d.getMonth() + 1) + '-' + p2(d.getDate()) + ' ' +
30
+ p2(d.getHours()) + ':' + p2(d.getMinutes()) + ':' + p2(d.getSeconds());
31
+ }
32
+ /** 从备份文件名解析时间(毫秒与老家六位微秒两种后缀都认)。 */
33
+ function parseStamp(name) {
34
+ const m = /^home_backup_(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})(?:_(\d{1,6}))?\.zip$/.exec(name);
35
+ if (!m)
36
+ return null;
37
+ const ms = m[7] ? Number(m[7].slice(0, 3).padEnd(3, '0')) : 0;
38
+ return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]), Number(m[4]), Number(m[5]), Number(m[6]), ms);
39
+ }
40
+ function daysBetween(from, to = new Date()) {
41
+ return Math.floor((to.getTime() - from.getTime()) / 86400000);
42
+ }
43
+ /** 备份目录名:配置 `backup.dir`,空串=默认(`backups`)。 */
44
+ export function backupDirName() {
45
+ const dir = loadHomeConfig().values.backup.dir;
46
+ return dir === '' ? DEFAULT_BACKUP_DIR_NAME : dir;
47
+ }
48
+ /** 备份目录(库目录下 `backups/`)——设置页「备份目录」那一项的取值口;只算路径,不建目录。 */
49
+ export function resolveBackupDir() {
50
+ return join(resolveDbDir(), backupDirName());
51
+ }
52
+ function backupFiles(dir) {
53
+ if (!existsSync(dir))
54
+ return [];
55
+ return readdirSync(dir).filter((f) => f.startsWith(BACKUP_PREFIX) && f.endsWith('.zip')).sort();
56
+ }
57
+ function readHistory(dir) {
58
+ return backupFiles(dir).map((f) => {
59
+ const st = statSync(join(dir, f));
60
+ return { file: f, size: st.size, created_at: nowStr(st.mtime), days_ago: daysBetween(st.mtime) };
61
+ });
62
+ }
63
+ function daysSinceLast(dir) {
64
+ const files = backupFiles(dir);
65
+ if (!files.length)
66
+ return null;
67
+ const t = parseStamp(files[files.length - 1]);
68
+ return t ? daysBetween(t) : null;
69
+ }
70
+ function pruneBackups(dir, keepN) {
71
+ const files = backupFiles(dir);
72
+ for (const old of files.slice(0, Math.max(0, files.length - keepN))) {
73
+ try {
74
+ unlinkSync(join(dir, old));
75
+ }
76
+ catch { /* 删不掉不挡本次备份,历史里仍在 */ }
77
+ }
78
+ }
79
+ function esc1(s) { return s.replace(/'/g, "''"); }
80
+ /** 备份:库快照(含 WAL)+ 清单打包成 zip,保留 N 份、删最旧;返回回执载荷。 */
81
+ export function createBackup(opts = {}) {
82
+ const keepN = opts.keepN ?? BACKUP_KEEP_N;
83
+ if (!Number.isInteger(keepN) || keepN <= 0)
84
+ throw new HomePolicyError('POLICY_BAD_INPUT', 'keep_n 须为正整数');
85
+ const dbPath = resolveDbPath();
86
+ if (!existsSync(dbPath))
87
+ throw new HomeFetchError('HOME_DB_MISSING', '库不存在,无可备份:' + dbPath);
88
+ const dir = resolveBackupDir();
89
+ mkdirSync(dir, { recursive: true });
90
+ const base = stamp();
91
+ let target = join(dir, BACKUP_PREFIX + base + '.zip');
92
+ for (let i = 1; existsSync(target); i++)
93
+ target = join(dir, BACKUP_PREFIX + base + '_' + i + '.zip');
94
+ let dbBytes;
95
+ let items = 0;
96
+ const snap = join(dir, '.snapshot-' + base + '.db');
97
+ try {
98
+ const handle = openHomeDb(dbPath);
99
+ try {
100
+ handle.db.exec("VACUUM INTO '" + esc1(snap) + "'");
101
+ items = Number(handle.db.prepare('SELECT count(*) AS c FROM items').get().c);
102
+ }
103
+ finally {
104
+ closeHomeDb(handle);
105
+ }
106
+ dbBytes = readFileSync(snap);
107
+ }
108
+ catch (e) {
109
+ throw new HomeFetchError('HOME_DB_UNREADABLE', '备份快照失败:' + e.message, { cause: e });
110
+ }
111
+ finally {
112
+ try {
113
+ if (existsSync(snap))
114
+ unlinkSync(snap);
115
+ }
116
+ catch { /* 临时件删不掉不挡备份 */ }
117
+ }
118
+ const created = nowStr();
119
+ const dbName = dbFilename();
120
+ const manifest = { schema_version: EXPORT_SCHEMA_VERSION, created_at: created, db_filename: dbName, items };
121
+ const entries = [
122
+ { name: dbName, data: dbBytes },
123
+ { name: 'manifest.json', data: Buffer.from(JSON.stringify(manifest, null, 1) + '\n', 'utf8') },
124
+ ];
125
+ try {
126
+ writeFileSync(target, zipWrite(entries));
127
+ }
128
+ catch (e) {
129
+ throw new HomeFetchError('HOME_DB_UNREADABLE', '备份写盘失败:' + target + '(' + e.message + ')', { cause: e });
130
+ }
131
+ pruneBackups(dir, keepN);
132
+ return {
133
+ status: 'ok', keep_n: keepN, file: target, size: statSync(target).size, created_at: created,
134
+ items, history: readHistory(dir), days_since_last: daysSinceLast(dir),
135
+ };
136
+ }
137
+ /** 备份历史:现读盘,不缓存(面板/回执要的是当前真状态)。 */
138
+ export function listBackups(opts = {}) {
139
+ const keepN = opts.keepN ?? BACKUP_KEEP_N;
140
+ const dir = resolveBackupDir();
141
+ const history = readHistory(dir);
142
+ return { status: 'ok', dir, keep_n: keepN, count: history.length, history, days_since_last: daysSinceLast(dir) };
143
+ }
144
+ function resolveBackupFile(file, dir) {
145
+ const abs = isAbsolute(file) ? file : join(dir, file);
146
+ const base = basename(abs);
147
+ if (!base.startsWith(BACKUP_PREFIX) || !base.endsWith('.zip')) {
148
+ throw new HomePolicyError('POLICY_BAD_INPUT', '备份文件名不合规(须 ' + BACKUP_PREFIX + '*.zip):' + base);
149
+ }
150
+ if (!existsSync(abs))
151
+ throw new HomePolicyError('POLICY_BAD_INPUT', '备份文件不存在:' + abs);
152
+ return abs;
153
+ }
154
+ function countItems(dbPath) {
155
+ if (!existsSync(dbPath))
156
+ return 0;
157
+ const handle = openHomeDb(dbPath);
158
+ try {
159
+ return Number(handle.db.prepare('SELECT count(*) AS c FROM items').get().c);
160
+ }
161
+ finally {
162
+ closeHomeDb(handle);
163
+ }
164
+ }
165
+ /**
166
+ * 导入恢复:拿备份里的 `home.db` 覆盖当前库;覆盖前先自备份一次(数据安全优先于便捷)。
167
+ * `dryRun`=预告支(SM8-4「文件选择(预告式)→ 校验 → 冲突预览 → 确认导入」的中间那一步):只校验+报数,不落盘。
168
+ */
169
+ export function restoreBackup(file, opts = {}) {
170
+ if (!file)
171
+ throw new HomePolicyError('POLICY_BAD_INPUT', '导入恢复须给 file(备份文件名或绝对路径)');
172
+ const src = resolveBackupFile(file, resolveBackupDir());
173
+ let entries;
174
+ let dbBytes;
175
+ try {
176
+ entries = zipRead(readFileSync(src));
177
+ const dbName = dbFilename();
178
+ const hit = entries.find((e) => e.name === dbName);
179
+ if (!hit)
180
+ throw new Error('备份内未找到 ' + dbName);
181
+ dbBytes = hit.data;
182
+ }
183
+ catch (e) {
184
+ throw new HomePolicyError('POLICY_BAD_INPUT', '备份文件无效:' + src + '(' + e.message + ')');
185
+ }
186
+ const dbPath = resolveDbPath();
187
+ if (opts.dryRun) {
188
+ const mf = entries.find((e) => e.name === 'manifest.json');
189
+ let inBackup = null;
190
+ if (mf) {
191
+ try {
192
+ const j = JSON.parse(mf.data.toString('utf8'));
193
+ if (typeof j.items === 'number')
194
+ inBackup = j.items;
195
+ }
196
+ catch { /* 清单坏就报 null,不谎报件数 */ }
197
+ }
198
+ const cur = countItems(dbPath);
199
+ return {
200
+ status: 'ok', dry_run: true, restored_from: src, items_in_backup: inBackup, items_current: cur,
201
+ message: '预告通过:这份备份' + (inBackup === null ? '(件数未知)' : '含 ' + inBackup + ' 件') +
202
+ ',当前库 ' + cur + ' 件;恢复会**整库覆盖**(恢复前自动自备份)。确认请给 confirm:true',
203
+ };
204
+ }
205
+ const safety = createBackup(opts);
206
+ // 覆盖前清掉 WAL/SHM:留着旧 WAL 会把刚恢复的库再改写坏。
207
+ for (const side of ['-wal', '-shm']) {
208
+ try {
209
+ if (existsSync(dbPath + side))
210
+ unlinkSync(dbPath + side);
211
+ }
212
+ catch { /* 清不掉则下面写入会大声失败 */ }
213
+ }
214
+ try {
215
+ writeFileSync(dbPath, dbBytes);
216
+ }
217
+ catch (e) {
218
+ throw new HomeFetchError('HOME_DB_UNREADABLE', '写回数据库失败:' + dbPath + '(' + e.message + ')', { cause: e });
219
+ }
220
+ let itemsTotal = 0;
221
+ try {
222
+ itemsTotal = countItems(dbPath);
223
+ }
224
+ catch (e) {
225
+ throw new HomeFetchError('HOME_DB_UNREADABLE', '恢复后库不可读:' + dbPath + '(' + e.message + ')', { cause: e });
226
+ }
227
+ return {
228
+ status: 'ok', restored_from: src, safety_backup: safety.file,
229
+ before_items: safety.items, items_total: itemsTotal,
230
+ message: '已从备份恢复:' + basename(src) + '(恢复前已自备份)',
231
+ };
232
+ }
233
+ function csvCell(v) {
234
+ if (v === null || v === undefined)
235
+ return '';
236
+ const s = String(v);
237
+ return /[",\n\r]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s;
238
+ }
239
+ const CSV_COLS = [
240
+ 'id', 'name', 'category', 'owner', 'purchase_price', 'remark',
241
+ 'location', 'quantity', 'location_status', 'purchase_date', 'expiration_date',
242
+ ];
243
+ /** 导出:JSON=全表可迁移;CSV=物品 ⋈ 位置便携(列与老家 ops.py:620 逐列相同)。 */
244
+ export function exportData(opts = {}) {
245
+ const format = String(opts.format ?? 'json').toLowerCase();
246
+ if (format !== 'json' && format !== 'csv') {
247
+ throw new HomePolicyError('POLICY_BAD_INPUT', '不支持的格式:' + opts.format + '(只认 json/csv)');
248
+ }
249
+ const dbPath = resolveDbPath();
250
+ if (!existsSync(dbPath))
251
+ throw new HomeFetchError('HOME_DB_MISSING', '库不存在,无可导出:' + dbPath);
252
+ let text = '';
253
+ let rows = 0;
254
+ const handle = openHomeDb(dbPath);
255
+ try {
256
+ if (format === 'json') {
257
+ const items = handle.db.prepare('SELECT * FROM items').all();
258
+ const data = {
259
+ schema_version: EXPORT_SCHEMA_VERSION,
260
+ exported_at: nowStr(),
261
+ items,
262
+ item_locations: handle.db.prepare('SELECT * FROM item_locations').all(),
263
+ item_tags: handle.db.prepare('SELECT * FROM item_tags').all(),
264
+ categories: handle.db.prepare('SELECT * FROM categories').all(),
265
+ };
266
+ rows = items.length;
267
+ text = JSON.stringify(data, null, 1) + '\n';
268
+ }
269
+ else {
270
+ const rs = handle.db.prepare('SELECT i.id, i.name, i.category, i.owner, i.purchase_price, i.remark, ' +
271
+ 'l.location, l.quantity, l.location_status, l.purchase_date, l.expiration_date ' +
272
+ 'FROM items i LEFT JOIN item_locations l ON l.item_id = i.id ORDER BY i.id').all();
273
+ rows = rs.length;
274
+ text = [CSV_COLS.join(','), ...rs.map((r) => CSV_COLS.map((c) => csvCell(r[c])).join(','))].join('\n') + '\n';
275
+ }
276
+ }
277
+ finally {
278
+ closeHomeDb(handle);
279
+ }
280
+ const out = opts.output
281
+ ? resolve(opts.output)
282
+ : join(resolveBackupDir(), 'home_export_' + stamp().replace(/_\d{3}$/, '') + (format === 'json' ? '.json' : '.csv'));
283
+ try {
284
+ mkdirSync(dirname(out), { recursive: true });
285
+ writeFileSync(out, text, 'utf8');
286
+ }
287
+ catch (e) {
288
+ throw new HomeFetchError('HOME_DB_UNREADABLE', '导出写盘失败:' + out + '(' + e.message + ')', { cause: e });
289
+ }
290
+ return { status: 'ok', file: out, format, size: Buffer.byteLength(text, 'utf8'), rows };
291
+ }
292
+ //# sourceMappingURL=backup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/fetch/backup.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  export { HomeFetchError, HomePolicyError } from './errors.js';
2
2
  export { SCHEMA_VERSION, openHomeDb, closeHomeDb, addItem, getItemById, listLocationsByItem, listTagsByItem, searchItems, updateItem, adjustQuantity, setLocationStatus, moveLocation, setItemTags, listAllTags, mergeTags, listCategories, getCategoryById, encryptPassword, decryptPassword, assertMasterKey, } from './db.js';
3
3
  export type { HomeItem, HomeLocation, HomeDb, SearchFilter } from './db.js';
4
- export { resolveDbDir, resolveDbPath, assertWritablePath, DB_FILENAME } from './paths.js';
4
+ export { resolveDbDir, resolveDbPath, dbFilename, DEFAULT_DB_FILENAME } from './paths.js';
5
+ export { resolveBackupDir, createBackup, listBackups, restoreBackup, exportData } from './backup.js';
5
6
  export { addInventoryRecord, listInventoryRecords, listLocationNodes, ensureLocationNode, listShopping, addShopping, checkShopping, missingItems, stockList, setThreshold, listPurchases, addPurchase, purchaseYearStats, listWarranties, addWarranty, addServiceEvent, listCerts, addCert, listAccounts, listMembers, addMember, listBorrows, addBorrow, statsOverview, highFreq, idleItems, expiringItems, } from './domains.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fetch/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EACL,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAC7D,mBAAmB,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAC5E,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EACpE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,GACnF,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC1F,OAAO,EACL,kBAAkB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,kBAAkB,EAC/E,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAC/E,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAC3F,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAChF,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,GAClD,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fetch/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EACL,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAC7D,mBAAmB,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAC5E,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EACpE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,GACnF,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE1F,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrG,OAAO,EACL,kBAAkB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,kBAAkB,EAC/E,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAC/E,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAC3F,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAChF,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,GAClD,MAAM,cAAc,CAAC"}
@@ -1,5 +1,7 @@
1
1
  export { HomeFetchError, HomePolicyError } from './errors.js';
2
2
  export { SCHEMA_VERSION, openHomeDb, closeHomeDb, addItem, getItemById, listLocationsByItem, listTagsByItem, searchItems, updateItem, adjustQuantity, setLocationStatus, moveLocation, setItemTags, listAllTags, mergeTags, listCategories, getCategoryById, encryptPassword, decryptPassword, assertMasterKey, } from './db.js';
3
- export { resolveDbDir, resolveDbPath, assertWritablePath, DB_FILENAME } from './paths.js';
3
+ export { resolveDbDir, resolveDbPath, dbFilename, DEFAULT_DB_FILENAME } from './paths.js';
4
+ // #707:备份导出/导入恢复(HELP SM8-3/SM8-4)的落点。
5
+ export { resolveBackupDir, createBackup, listBackups, restoreBackup, exportData } from './backup.js';
4
6
  export { addInventoryRecord, listInventoryRecords, listLocationNodes, ensureLocationNode, listShopping, addShopping, checkShopping, missingItems, stockList, setThreshold, listPurchases, addPurchase, purchaseYearStats, listWarranties, addWarranty, addServiceEvent, listCerts, addCert, listAccounts, listMembers, addMember, listBorrows, addBorrow, statsOverview, highFreq, idleItems, expiringItems, } from './domains.js';
5
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fetch/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EACL,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAC7D,mBAAmB,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAC5E,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EACpE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,GACnF,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC1F,OAAO,EACL,kBAAkB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,kBAAkB,EAC/E,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAC/E,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAC3F,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAChF,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,GAClD,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fetch/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EACL,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAC7D,mBAAmB,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAC5E,iBAAiB,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EACpE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,GACnF,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC1F,uCAAuC;AACvC,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrG,OAAO,EACL,kBAAkB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,kBAAkB,EAC/E,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAC/E,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAC3F,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAChF,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,GAClD,MAAM,cAAc,CAAC"}
@@ -1,6 +1,8 @@
1
- export declare const DB_FILENAME = "home.db";
1
+ /** 库文件名的默认值:=改造前的代码常量 `DB_FILENAME`(配置项 `db.name` 空串即用它)。 */
2
+ export declare const DEFAULT_DB_FILENAME = "home.db";
3
+ /** 库文件名:配置 `db.name`,空串=默认(`home.db`)。 */
4
+ export declare function dbFilename(): string;
5
+ /** 库目录:配置 `db.dir`,空串=数据目录(`~/.ilife/data/`,`ILIFE_CONFIG_DIR` 可整体接管)。 */
2
6
  export declare function resolveDbDir(): string;
3
7
  export declare function resolveDbPath(filename?: string, dir?: string): string;
4
- /** 测试隔离守卫:非 tmp 路径写库须 HOME_FORCE_PROD=1(卡路里哨兵语义的居家版)。 */
5
- export declare function assertWritablePath(dbPath: string): void;
6
8
  //# sourceMappingURL=paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/fetch/paths.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,wBAAgB,YAAY,IAAI,MAAM,CASrC;AAED,wBAAgB,aAAa,CAAC,QAAQ,SAAc,EAAE,GAAG,SAAiB,GAAG,MAAM,CAGlF;AAED,yDAAyD;AACzD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAYvD"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/fetch/paths.ts"],"names":[],"mappings":"AAUA,6DAA6D;AAC7D,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAE7C,0CAA0C;AAC1C,wBAAgB,UAAU,IAAI,MAAM,CAGnC;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,IAAI,MAAM,CAGrC;AAED,wBAAgB,aAAa,CAAC,QAAQ,SAAe,EAAE,GAAG,SAAiB,GAAG,MAAM,CAGnF"}
@@ -1,31 +1,26 @@
1
- // DB 路径解析与隔离守卫:SKILLS_DB_PATH 必设,无默认值(铁律缺失阻断)。
2
- // 老家 home_manager/db.py Q6 fallback 链(D:/.db 等)TS 线有意不继承:拒绝隐式写生产。
1
+ // 库路径解析:**配置文件的唯一真相**(#695;口径见「配置的存与生效口径裁定」#675 的解决评论)。
2
+ // 改造前这里读 `SKILLS_DB_PATH`(无默认值、缺失即抛),并按 `HOME_FORCE_PROD=1` 守「非 tmp 不许写库」;
3
+ // #695 按用户裁决把两个环境变量**一并删掉**:路径改从 `~/.ilife/home.yaml` 取,写库边界改由
4
+ // 「测试基座强制 `ILIFE_CONFIG_DIR`」(`base-link-core` 的 `CONFIG_TEST_ISOLATION_MISSING`)承担——
5
+ // 把「忘了配」从静默写真实库变成响亮失败。
6
+ // 老家 home_manager/db.py Q6 fallback 链(D:/.db 等)TS 线仍有意不继承:拒绝隐式写生产。
3
7
  import { mkdirSync } from 'node:fs';
4
- import { tmpdir } from 'node:os';
5
- import { join, resolve } from 'node:path';
6
- export const DB_FILENAME = 'home.db';
8
+ import { join } from 'node:path';
9
+ import { loadHomeConfig } from '../config.js';
10
+ /** 库文件名的默认值:=改造前的代码常量 `DB_FILENAME`(配置项 `db.name` 空串即用它)。 */
11
+ export const DEFAULT_DB_FILENAME = 'home.db';
12
+ /** 库文件名:配置 `db.name`,空串=默认(`home.db`)。 */
13
+ export function dbFilename() {
14
+ const name = loadHomeConfig().values.db.name;
15
+ return name === '' ? DEFAULT_DB_FILENAME : name;
16
+ }
17
+ /** 库目录:配置 `db.dir`,空串=数据目录(`~/.ilife/data/`,`ILIFE_CONFIG_DIR` 可整体接管)。 */
7
18
  export function resolveDbDir() {
8
- const env = process.env.SKILLS_DB_PATH;
9
- if (!env) {
10
- throw new Error('[skill-home] SKILLS_DB_PATH 未设置:拒绝隐式落盘。' +
11
- '生产请设置 SKILLS_DB_PATH;测试请传显式 tmp 路径。');
12
- }
13
- return env;
19
+ const dir = loadHomeConfig().values.db.dir;
20
+ return dir === '' ? loadHomeConfig().dataDir : dir;
14
21
  }
15
- export function resolveDbPath(filename = DB_FILENAME, dir = resolveDbDir()) {
22
+ export function resolveDbPath(filename = dbFilename(), dir = resolveDbDir()) {
16
23
  mkdirSync(dir, { recursive: true });
17
24
  return join(dir, filename);
18
25
  }
19
- /** 测试隔离守卫:非 tmp 路径写库须 HOME_FORCE_PROD=1(卡路里哨兵语义的居家版)。 */
20
- export function assertWritablePath(dbPath) {
21
- const forceProd = process.env.HOME_FORCE_PROD === '1';
22
- const underTmp = resolve(dbPath).startsWith(resolve(tmpdir()));
23
- if (!underTmp && !forceProd) {
24
- throw new Error('[skill-home] 拒绝写入非 tmp 路径 ' + dbPath + ':测试隔离守卫。' +
25
- '如确需生产写,请设置 HOME_FORCE_PROD=1(opt-in 可见)。');
26
- }
27
- if (!underTmp && forceProd) {
28
- console.error('[skill-home] HOME_FORCE_PROD=1: 写入 ' + dbPath);
29
- }
30
- }
31
26
  //# sourceMappingURL=paths.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/fetch/paths.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,kEAAkE;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AAErC,MAAM,UAAU,YAAY;IAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IACvC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,yCAAyC;YACvC,qCAAqC,CACxC,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAQ,GAAG,WAAW,EAAE,GAAG,GAAG,YAAY,EAAE;IACxE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,GAAG,CAAC;IACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC/D,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,4BAA4B,GAAG,MAAM,GAAG,UAAU;YAChD,0CAA0C,CAC7C,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,QAAQ,IAAI,SAAS,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,qCAAqC,GAAG,MAAM,CAAC,CAAC;IAChE,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/fetch/paths.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,2EAA2E;AAC3E,+DAA+D;AAC/D,sFAAsF;AACtF,uBAAuB;AACvB,mEAAmE;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,6DAA6D;AAC7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,SAAS,CAAC;AAE7C,0CAA0C;AAC1C,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC;IAC7C,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,YAAY;IAC1B,MAAM,GAAG,GAAG,cAAc,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC;IAC3C,OAAO,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAQ,GAAG,UAAU,EAAE,EAAE,GAAG,GAAG,YAAY,EAAE;IACzE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,41 @@
1
+ /** 报告里的三档判据(与面板侧镜像同值)。 */
2
+ export type HealthStatus = 'red' | 'yellow' | 'green';
3
+ export interface HealthItem {
4
+ readonly id: string;
5
+ readonly title: string;
6
+ readonly status: HealthStatus;
7
+ readonly message: string;
8
+ readonly action: string;
9
+ readonly source?: string;
10
+ }
11
+ export interface HomeHealthReport {
12
+ readonly skill: string;
13
+ readonly configPath: string;
14
+ readonly dataDir: string;
15
+ readonly items: readonly HealthItem[];
16
+ }
17
+ /** 库表数门槛:`src/fetch/db.ts` 的建表语句里那 16 张表齐了才算正常(少了报黄:还能用,但缺功能的表要重建)。 */
18
+ export declare const DB_TABLE_THRESHOLD: 16;
19
+ /** 只读解析结果:文件不在/读得出取值与「哪些键真在文件里」/读不出来(报文带行号与文件名)。 */
20
+ export type ConfigRead = {
21
+ readonly kind: 'missing';
22
+ } | {
23
+ readonly kind: 'ok';
24
+ readonly values: Record<string, Record<string, unknown>>;
25
+ readonly present: ReadonlySet<string>;
26
+ } | {
27
+ readonly kind: 'bad';
28
+ readonly message: string;
29
+ };
30
+ /**
31
+ * 只读解析那份配置文件(与 `base-link-core` 的受限子集同一套校验,口径逐条对齐):
32
+ * 剥 BOM、去 `\r`、空行与整行注释跳过、缩进只许 2 个空格且不许制表符、不支持列表、
33
+ * 一行须是「键: 值」、不许重复定义、顶层键冒号后没值即开一个组。
34
+ *
35
+ * 与 `loadConfig()` 的差别只有一处、也正是本件要的那一处:**文件不在时不落默认件**。
36
+ * 取值语义与它一致:文件里缺的项按默认值补。
37
+ */
38
+ export declare function readHomeConfigReadOnly(): ConfigRead;
39
+ /** 跑一次体检,返回整份报告。**只读**:任何一处都不落盘(只有写探针那一个文件,且当场删掉)。 */
40
+ export declare function buildHomeHealthReport(): HomeHealthReport;
41
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../src/health.ts"],"names":[],"mappings":"AA4BA,0BAA0B;AAC1B,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;CACvC;AAED,uEAAuE;AACvE,eAAO,MAAM,kBAAkB,EAAG,EAAW,CAAC;AAiB9C,oDAAoD;AACpD,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAAE,GACxH;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,IAAI,UAAU,CAYnD;AAsRD,sDAAsD;AACtD,wBAAgB,qBAAqB,IAAI,gBAAgB,CA4KxD"}