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.
- package/SKILL.md +17 -17
- package/dist/cli/cmd_read.js +93 -26
- package/dist/cli/cmd_read.js.map +1 -1
- package/dist/cli/config.d.ts +16 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +84 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/health.d.ts +7 -0
- package/dist/cli/health.d.ts.map +1 -0
- package/dist/cli/health.js +32 -0
- package/dist/cli/health.js.map +1 -0
- package/dist/config.d.ts +44 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +65 -0
- package/dist/config.js.map +1 -0
- package/dist/fetch/archive.d.ts +13 -0
- package/dist/fetch/archive.d.ts.map +1 -0
- package/dist/fetch/archive.js +115 -0
- package/dist/fetch/archive.js.map +1 -0
- package/dist/fetch/backup.d.ts +77 -0
- package/dist/fetch/backup.d.ts.map +1 -0
- package/dist/fetch/backup.js +292 -0
- package/dist/fetch/backup.js.map +1 -0
- package/dist/fetch/index.d.ts +2 -1
- package/dist/fetch/index.d.ts.map +1 -1
- package/dist/fetch/index.js +3 -1
- package/dist/fetch/index.js.map +1 -1
- package/dist/fetch/paths.d.ts +5 -3
- package/dist/fetch/paths.d.ts.map +1 -1
- package/dist/fetch/paths.js +19 -24
- package/dist/fetch/paths.js.map +1 -1
- package/dist/health.d.ts +41 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +507 -0
- package/dist/health.js.map +1 -0
- package/dist/help/helpFile.d.ts +1 -1
- package/dist/help/manifest.d.ts +7 -19
- package/dist/help/manifest.d.ts.map +1 -1
- package/dist/help/manifest.js +22 -7
- package/dist/help/manifest.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** 体检命令名(插件侧镜像同值,见 `packages/plugin-home-ilife/src/bridge.ts`)。 */
|
|
2
|
+
export declare const HEALTH_CHECK_KEY: "home.config.check";
|
|
3
|
+
/** 是不是体检命令(分派层拦截用)。 */
|
|
4
|
+
export declare function isHealthCheckKey(key: string): boolean;
|
|
5
|
+
/** 跑一次体检,返回整行 envelope JSON(`data` 即那份报告)。 */
|
|
6
|
+
export declare function runHealthCheckKey(key: string): string;
|
|
7
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/cli/health.ts"],"names":[],"mappings":"AAaA,mEAAmE;AACnE,eAAO,MAAM,gBAAgB,EAAG,mBAA4B,CAAC;AAK7D,uBAAuB;AACvB,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUrD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** 配置体检这个只读命令的**技能入口装配**:把 `src/health.ts` 的报告包成唯一出口那行 envelope。
|
|
2
|
+
*
|
|
3
|
+
* 为什么这个 key 与三个配置命令同住 `cli/config.ts` 的旁边、而不进 `src/policy/wakewords.ts` 那张唤醒词表:
|
|
4
|
+
* 那张表管的是**唤醒词命令**(短语→key→形状→示例),要进 HELP 与唤醒词计数。体检是**设置页专用**的只读
|
|
5
|
+
* 出口(面板点一下才跑),没有唤醒词、不进 HELP,故按「一条命令的事实只住一处」与三个配置命令并列;
|
|
6
|
+
* `cmd_read.ts` 在**进预检与分派层之前**拦下它(体检不该要求库目录已配——它要报的正是「库在哪、通不通」)。
|
|
7
|
+
*
|
|
8
|
+
* 判据与文案住在 `src/health.ts`;本件只做包封,不重写一个字。
|
|
9
|
+
*/
|
|
10
|
+
import { ENVELOPE_VERSION } from 'base-link-core';
|
|
11
|
+
import { buildHomeHealthReport } from '../health.js';
|
|
12
|
+
/** 体检命令名(插件侧镜像同值,见 `packages/plugin-home-ilife/src/bridge.ts`)。 */
|
|
13
|
+
export const HEALTH_CHECK_KEY = 'home.config.check';
|
|
14
|
+
/** 本技能的 envelope skill 名(与 `src/render/envelope.ts` 的 `createEnvelope({skill:'home'})` 同值)。 */
|
|
15
|
+
const HOME_SKILL = 'home';
|
|
16
|
+
/** 是不是体检命令(分派层拦截用)。 */
|
|
17
|
+
export function isHealthCheckKey(key) {
|
|
18
|
+
return key === HEALTH_CHECK_KEY;
|
|
19
|
+
}
|
|
20
|
+
/** 跑一次体检,返回整行 envelope JSON(`data` 即那份报告)。 */
|
|
21
|
+
export function runHealthCheckKey(key) {
|
|
22
|
+
const report = buildHomeHealthReport();
|
|
23
|
+
const envelope = {
|
|
24
|
+
version: ENVELOPE_VERSION,
|
|
25
|
+
skill: HOME_SKILL,
|
|
26
|
+
shape: 'detail',
|
|
27
|
+
key,
|
|
28
|
+
data: report,
|
|
29
|
+
};
|
|
30
|
+
return JSON.stringify(envelope);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/cli/health.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD,mEAAmE;AACnE,MAAM,CAAC,MAAM,gBAAgB,GAAG,mBAA4B,CAAC;AAE7D,+FAA+F;AAC/F,MAAM,UAAU,GAAG,MAAe,CAAC;AAEnC,uBAAuB;AACvB,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,OAAO,GAAG,KAAK,gBAAgB,CAAC;AAClC,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAG;QACf,OAAO,EAAE,gBAAgB;QACzB,KAAK,EAAE,UAAU;QACjB,KAAK,EAAE,QAAyB;QAChC,GAAG;QACH,IAAI,EAAE,MAAM;KACb,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;AAClC,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ConfigRecord } from 'base-link-core';
|
|
2
|
+
/** 配置文件主体名:`<配置目录>/home.yaml`。 */
|
|
3
|
+
export declare const HOME_CONFIG_STEM: "home";
|
|
4
|
+
/** 居家管家那份配置表:键即设置页的行,一层嵌套(子集支持范围见 base-link-core README)。 */
|
|
5
|
+
export declare const HOME_CONFIG_DEFAULTS: {
|
|
6
|
+
db: {
|
|
7
|
+
dir: string;
|
|
8
|
+
name: string;
|
|
9
|
+
};
|
|
10
|
+
html: {
|
|
11
|
+
dir: string;
|
|
12
|
+
};
|
|
13
|
+
files: {
|
|
14
|
+
help: string;
|
|
15
|
+
lookup: string;
|
|
16
|
+
};
|
|
17
|
+
backup: {
|
|
18
|
+
dir: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
/** 取值形状由默认值表派生(同一件事只有一个定义地)。 */
|
|
22
|
+
export type HomeConfigValues = typeof HOME_CONFIG_DEFAULTS;
|
|
23
|
+
/** 读回来的一份配置:文件路径(人话报错要指它)+数据目录+取值。 */
|
|
24
|
+
export interface LoadedHomeConfig {
|
|
25
|
+
readonly path: string;
|
|
26
|
+
readonly dataDir: string;
|
|
27
|
+
readonly created: boolean;
|
|
28
|
+
readonly values: HomeConfigValues;
|
|
29
|
+
}
|
|
30
|
+
/** 读一份配置(文件不存在即按默认值落一份并把配置目录/数据目录建出来)。 */
|
|
31
|
+
export declare function loadHomeConfig(): LoadedHomeConfig;
|
|
32
|
+
/** 写一份配置(写出去的是完整一份:没给的项按默认值补齐)。写完清记忆,同进程后续读也现取。 */
|
|
33
|
+
export declare function saveHomeConfig(values: ConfigRecord): {
|
|
34
|
+
path: string;
|
|
35
|
+
};
|
|
36
|
+
/** 重置为默认(先另存 `<配置目录>/home.yaml.bak`)。 */
|
|
37
|
+
export declare function resetHomeConfig(): {
|
|
38
|
+
path: string;
|
|
39
|
+
backupPath: string | null;
|
|
40
|
+
};
|
|
41
|
+
/** 把配置里的相对段串拆成段(`home_manager_html` → `['home_manager_html']`;`\` 与 `/` 都认,
|
|
42
|
+
* 空段丢弃——Windows 用户手写路径时两种分隔符都会用)。段数由值决定,故「几段」这件事配置形状能表达。 */
|
|
43
|
+
export declare function splitDirSegments(value: string): string[];
|
|
44
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,kCAAkC;AAClC,eAAO,MAAM,gBAAgB,EAAG,MAAe,CAAC;AAEhD,6DAA6D;AAC7D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;CAKhC,CAAC;AAEF,gCAAgC;AAChC,MAAM,MAAM,gBAAgB,GAAG,OAAO,oBAAoB,CAAC;AAE3D,sCAAsC;AACtC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;CACnC;AAKD,0CAA0C;AAC1C,wBAAgB,cAAc,IAAI,gBAAgB,CAajD;AAED,mDAAmD;AACnD,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAIrE;AAED,yCAAyC;AACzC,wBAAgB,eAAe,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAI7E;AAED;6DAC6D;AAC7D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAExD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** 居家管家自己的配置面:那份默认值表 + 读/写/重置三个薄转调。
|
|
2
|
+
*
|
|
3
|
+
* 口径出处(「配置的存与生效口径裁定」#675 的解决评论,本票 #695 落地):**每个技能一份 YAML 配置文件,
|
|
4
|
+
* 配置文件是唯一真相,环境变量不参与配置**。默认落点 `~/.ilife/home.yaml`(由 `os.homedir()` 派生,
|
|
5
|
+
* 平台无关),`ILIFE_CONFIG_DIR` 设定且非空即整体接管配置目录;数据目录默认 `~/.ilife/data/`,
|
|
6
|
+
* 首次读时自动建;「重置为默认」先另存 `<配置目录>/home.yaml.bak`。
|
|
7
|
+
*
|
|
8
|
+
* 读写实现(受限 YAML 子集解析、键表与类型校验、备份、建目录)住 `base-link-core` 的 `src/config/`
|
|
9
|
+
* ——#694 已交付,本件只做「居家管家的那份表 + 转调」,一份实现不抄第二处(结构纪律铁律一)。
|
|
10
|
+
*
|
|
11
|
+
* 默认值逐项等于改造前的代码常量(对照读数见 `docs/skills/skill-home/t695-证据.md`):
|
|
12
|
+
* · `db.dir`=`''`(空串=按默认落点:数据目录 `~/.ilife/data/`,由取用处算——见 `src/fetch/paths.ts`);
|
|
13
|
+
* · `db.name`=`home.db`(原 `src/fetch/paths.ts` 的 `DB_FILENAME`);
|
|
14
|
+
* · `html.dir`=`home_manager_html`(原 `src/help/manifest.ts` 的 `HELP_HTML_DIR_NAME`——家是**一段**目录,
|
|
15
|
+
* 配置形状是字符串、段间用 `/` 或 `\` 分隔,因为受限子集不收数组;见 `base-link-core/README.md` §支持范围);
|
|
16
|
+
* · `files.help`/`files.lookup`=`居家管家_HELP`/`居家管家_速查表`(原 `manifest.ts` 的两个主体名);
|
|
17
|
+
* · `backup.dir`=`backups`(原 `src/fetch/backup.ts` 的 `BACKUP_DIR_NAME`,老家 `ops.py:26` 同值)。
|
|
18
|
+
* 用法上一处约定:**空串=按默认落点**——`db.dir` 空即用数据目录,由取用处算,
|
|
19
|
+
* 所以空串不是「没配」,老数据不会看起来丢了。
|
|
20
|
+
*/
|
|
21
|
+
import { loadConfig, resetConfig, saveConfig } from 'base-link-core';
|
|
22
|
+
/** 配置文件主体名:`<配置目录>/home.yaml`。 */
|
|
23
|
+
export const HOME_CONFIG_STEM = 'home';
|
|
24
|
+
/** 居家管家那份配置表:键即设置页的行,一层嵌套(子集支持范围见 base-link-core README)。 */
|
|
25
|
+
export const HOME_CONFIG_DEFAULTS = {
|
|
26
|
+
db: { dir: '', name: 'home.db' },
|
|
27
|
+
html: { dir: 'home_manager_html' },
|
|
28
|
+
files: { help: '居家管家_HELP', lookup: '居家管家_速查表' },
|
|
29
|
+
backup: { dir: 'backups' },
|
|
30
|
+
};
|
|
31
|
+
/** 每进程只读一次:配置文件的「保存即生效」靠**下一次调用现读**,同一个进程里不反复读盘。 */
|
|
32
|
+
let memo = null;
|
|
33
|
+
/** 读一份配置(文件不存在即按默认值落一份并把配置目录/数据目录建出来)。 */
|
|
34
|
+
export function loadHomeConfig() {
|
|
35
|
+
if (memo === null) {
|
|
36
|
+
const loaded = loadConfig(HOME_CONFIG_STEM, HOME_CONFIG_DEFAULTS);
|
|
37
|
+
// base-link-core 读回来时已经过了「键齐 + 类型对」两道校验(不认识的键、类型不符一律抛),
|
|
38
|
+
// 故这一处从宽松记录到形状记录的转换是有依据的投影,不是猜测。
|
|
39
|
+
memo = {
|
|
40
|
+
path: loaded.path,
|
|
41
|
+
dataDir: loaded.dataDir,
|
|
42
|
+
created: loaded.created,
|
|
43
|
+
values: loaded.values,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return memo;
|
|
47
|
+
}
|
|
48
|
+
/** 写一份配置(写出去的是完整一份:没给的项按默认值补齐)。写完清记忆,同进程后续读也现取。 */
|
|
49
|
+
export function saveHomeConfig(values) {
|
|
50
|
+
const r = saveConfig(HOME_CONFIG_STEM, HOME_CONFIG_DEFAULTS, values);
|
|
51
|
+
memo = null;
|
|
52
|
+
return r;
|
|
53
|
+
}
|
|
54
|
+
/** 重置为默认(先另存 `<配置目录>/home.yaml.bak`)。 */
|
|
55
|
+
export function resetHomeConfig() {
|
|
56
|
+
const r = resetConfig(HOME_CONFIG_STEM, HOME_CONFIG_DEFAULTS);
|
|
57
|
+
memo = null;
|
|
58
|
+
return r;
|
|
59
|
+
}
|
|
60
|
+
/** 把配置里的相对段串拆成段(`home_manager_html` → `['home_manager_html']`;`\` 与 `/` 都认,
|
|
61
|
+
* 空段丢弃——Windows 用户手写路径时两种分隔符都会用)。段数由值决定,故「几段」这件事配置形状能表达。 */
|
|
62
|
+
export function splitDirSegments(value) {
|
|
63
|
+
return value.split(/[\\/]+/).filter((s) => s.length > 0);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGrE,kCAAkC;AAClC,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAe,CAAC;AAEhD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;IAChC,IAAI,EAAE,EAAE,GAAG,EAAE,mBAAmB,EAAE;IAClC,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE;IAChD,MAAM,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE;CAC3B,CAAC;AAaF,oDAAoD;AACpD,IAAI,IAAI,GAA4B,IAAI,CAAC;AAEzC,0CAA0C;AAC1C,MAAM,UAAU,cAAc;IAC5B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,UAAU,CAAC,gBAAgB,EAAE,oBAAoB,CAAC,CAAC;QAClE,wDAAwD;QACxD,iCAAiC;QACjC,IAAI,GAAG;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,MAAM,EAAE,MAAM,CAAC,MAAqC;SACrD,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,MAAM,CAAC,GAAG,UAAU,CAAC,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,CAAC,CAAC;IACrE,IAAI,GAAG,IAAI,CAAC;IACZ,OAAO,CAAC,CAAC;AACX,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,GAAG,WAAW,CAAC,gBAAgB,EAAE,oBAAoB,CAAC,CAAC;IAC9D,IAAI,GAAG,IAAI,CAAC;IACZ,OAAO,CAAC,CAAC;AACX,CAAC;AAED;6DAC6D;AAC7D,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ZipEntry {
|
|
2
|
+
name: string;
|
|
3
|
+
data: Buffer;
|
|
4
|
+
}
|
|
5
|
+
export interface ZipReadEntry {
|
|
6
|
+
name: string;
|
|
7
|
+
data: Buffer;
|
|
8
|
+
}
|
|
9
|
+
/** 打包:条目按给定顺序写入,逐个 deflate(压不小就退回 stored,两种都合法)。 */
|
|
10
|
+
export declare function zipWrite(entries: ZipEntry[]): Buffer;
|
|
11
|
+
/** 解包:从 EOCD 走中央目录取每个条目的偏移,再读本地头与数据。 */
|
|
12
|
+
export declare function zipRead(buf: Buffer): ZipReadEntry[];
|
|
13
|
+
//# sourceMappingURL=archive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/fetch/archive.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAqCD,oDAAoD;AACpD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,CA6BpD;AAED,wCAAwC;AACxC,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,EAAE,CAiCnD"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// 备份容器:条目的打包与解包(ZIP 的最小可用子集,只用 node:zlib,不引外部依赖)。
|
|
2
|
+
//
|
|
3
|
+
// 为什么自己写而不引 zip 库:本仓规矩是不加外部依赖(见地图 #671 Notes 的冻结口径);
|
|
4
|
+
// 而备份产物要**用户能直接双击打开 / 拿系统解压**,故格式必须是 ZIP 而不是 tar.gz。
|
|
5
|
+
// 只做写与读各自必需的部分——不做流式、不做 ZIP64、不做加密、不收目录树(调用方给扁平条目表)。
|
|
6
|
+
// 读侧只认「无数据描述符(bit 3 = 0)+ stored/deflate」两条;其余一律带原因抛错,不静默跳过。
|
|
7
|
+
import { deflateRawSync, inflateRawSync } from 'node:zlib';
|
|
8
|
+
const SIG_LOCAL = 0x04034b50;
|
|
9
|
+
const SIG_CENTRAL = 0x02014b50;
|
|
10
|
+
const SIG_EOCD = 0x06054b50;
|
|
11
|
+
// msdos 时间:秒只有 2 秒精度;备份时间戳另由文件名承载,这里给常数,不谎报时间。
|
|
12
|
+
const DOS_TIME = 0;
|
|
13
|
+
const DOS_DATE = 0x2821; // 2000-01-01
|
|
14
|
+
function u16(v) {
|
|
15
|
+
const b = Buffer.allocUnsafe(2);
|
|
16
|
+
b.writeUInt16LE(v, 0);
|
|
17
|
+
return b;
|
|
18
|
+
}
|
|
19
|
+
function u32(v) {
|
|
20
|
+
const b = Buffer.allocUnsafe(4);
|
|
21
|
+
b.writeUInt32LE(v >>> 0, 0);
|
|
22
|
+
return b;
|
|
23
|
+
}
|
|
24
|
+
const CRC_TABLE = (() => {
|
|
25
|
+
const t = new Int32Array(256);
|
|
26
|
+
for (let n = 0; n < 256; n++) {
|
|
27
|
+
let c = n;
|
|
28
|
+
for (let k = 0; k < 8; k++)
|
|
29
|
+
c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
|
30
|
+
t[n] = c;
|
|
31
|
+
}
|
|
32
|
+
return t;
|
|
33
|
+
})();
|
|
34
|
+
function crc32(buf) {
|
|
35
|
+
let c = -1;
|
|
36
|
+
for (let i = 0; i < buf.length; i++)
|
|
37
|
+
c = CRC_TABLE[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
|
|
38
|
+
return (c ^ -1) >>> 0;
|
|
39
|
+
}
|
|
40
|
+
/** 打包:条目按给定顺序写入,逐个 deflate(压不小就退回 stored,两种都合法)。 */
|
|
41
|
+
export function zipWrite(entries) {
|
|
42
|
+
const locals = [];
|
|
43
|
+
const centrals = [];
|
|
44
|
+
let offset = 0;
|
|
45
|
+
for (const e of entries) {
|
|
46
|
+
const name = Buffer.from(e.name, 'utf8');
|
|
47
|
+
const deflated = deflateRawSync(e.data, { level: 9 });
|
|
48
|
+
const stored = deflated.length >= e.data.length;
|
|
49
|
+
const body = stored ? e.data : deflated;
|
|
50
|
+
const method = stored ? 0 : 8;
|
|
51
|
+
const crc = crc32(e.data);
|
|
52
|
+
const local = Buffer.concat([
|
|
53
|
+
u32(SIG_LOCAL), u16(20), u16(0), u16(method), u16(DOS_TIME), u16(DOS_DATE),
|
|
54
|
+
u32(crc), u32(body.length), u32(e.data.length), u16(name.length), u16(0), name, body,
|
|
55
|
+
]);
|
|
56
|
+
locals.push(local);
|
|
57
|
+
centrals.push(Buffer.concat([
|
|
58
|
+
u32(SIG_CENTRAL), u16(20), u16(20), u16(0), u16(method), u16(DOS_TIME), u16(DOS_DATE),
|
|
59
|
+
u32(crc), u32(body.length), u32(e.data.length), u16(name.length),
|
|
60
|
+
u16(0), u16(0), u16(0), u16(0), u32(0), u32(offset), name,
|
|
61
|
+
]));
|
|
62
|
+
offset += local.length;
|
|
63
|
+
}
|
|
64
|
+
const central = Buffer.concat(centrals);
|
|
65
|
+
const eocd = Buffer.concat([
|
|
66
|
+
u32(SIG_EOCD), u16(0), u16(0), u16(entries.length), u16(entries.length),
|
|
67
|
+
u32(central.length), u32(offset), u16(0),
|
|
68
|
+
]);
|
|
69
|
+
return Buffer.concat([...locals, central, eocd]);
|
|
70
|
+
}
|
|
71
|
+
/** 解包:从 EOCD 走中央目录取每个条目的偏移,再读本地头与数据。 */
|
|
72
|
+
export function zipRead(buf) {
|
|
73
|
+
const eocd = buf.lastIndexOf(u32(SIG_EOCD));
|
|
74
|
+
if (eocd < 0)
|
|
75
|
+
throw new Error('不是 ZIP:未找到中央目录结尾记录');
|
|
76
|
+
const count = buf.readUInt16LE(eocd + 10);
|
|
77
|
+
let p = buf.readUInt32LE(eocd + 16);
|
|
78
|
+
const out = [];
|
|
79
|
+
for (let i = 0; i < count; i++) {
|
|
80
|
+
if (p + 46 > buf.length || buf.readUInt32LE(p) !== SIG_CENTRAL)
|
|
81
|
+
throw new Error('ZIP 中央目录第 ' + (i + 1) + ' 条损坏');
|
|
82
|
+
const method = buf.readUInt16LE(p + 10);
|
|
83
|
+
const crc = buf.readUInt32LE(p + 16);
|
|
84
|
+
const compSize = buf.readUInt32LE(p + 20);
|
|
85
|
+
const rawSize = buf.readUInt32LE(p + 24);
|
|
86
|
+
const nameLen = buf.readUInt16LE(p + 28);
|
|
87
|
+
const extraLen = buf.readUInt16LE(p + 30);
|
|
88
|
+
const commentLen = buf.readUInt16LE(p + 32);
|
|
89
|
+
const localOff = buf.readUInt32LE(p + 42);
|
|
90
|
+
const name = buf.toString('utf8', p + 46, p + 46 + nameLen);
|
|
91
|
+
if (localOff + 30 > buf.length || buf.readUInt32LE(localOff) !== SIG_LOCAL)
|
|
92
|
+
throw new Error('ZIP 条目缺少本地头:' + name);
|
|
93
|
+
if ((buf.readUInt16LE(localOff + 6) & 0x08) !== 0)
|
|
94
|
+
throw new Error('ZIP 条目用了数据描述符(不支持):' + name);
|
|
95
|
+
const lNameLen = buf.readUInt16LE(localOff + 26);
|
|
96
|
+
const lExtraLen = buf.readUInt16LE(localOff + 28);
|
|
97
|
+
const start = localOff + 30 + lNameLen + lExtraLen;
|
|
98
|
+
const body = buf.subarray(start, start + compSize);
|
|
99
|
+
let data;
|
|
100
|
+
if (method === 0)
|
|
101
|
+
data = Buffer.from(body);
|
|
102
|
+
else if (method === 8)
|
|
103
|
+
data = inflateRawSync(body);
|
|
104
|
+
else
|
|
105
|
+
throw new Error('ZIP 条目压缩方式不支持(method=' + method + '):' + name);
|
|
106
|
+
if (data.length !== rawSize)
|
|
107
|
+
throw new Error('ZIP 条目长度不符:' + name);
|
|
108
|
+
if (crc32(data) !== crc)
|
|
109
|
+
throw new Error('ZIP 条目校验和不符(备份可能损坏):' + name);
|
|
110
|
+
out.push({ name, data });
|
|
111
|
+
p += 46 + nameLen + extraLen + commentLen;
|
|
112
|
+
}
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=archive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/fetch/archive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/** 备份目录名的默认值:=改造前的代码常量 `BACKUP_DIR_NAME`(配置项 `backup.dir` 空串即用它)。 */
|
|
2
|
+
export declare const DEFAULT_BACKUP_DIR_NAME = "backups";
|
|
3
|
+
export interface BackupRow {
|
|
4
|
+
file: string;
|
|
5
|
+
size: number;
|
|
6
|
+
created_at: string;
|
|
7
|
+
days_ago: number;
|
|
8
|
+
}
|
|
9
|
+
export interface BackupResult {
|
|
10
|
+
status: 'ok';
|
|
11
|
+
keep_n: number;
|
|
12
|
+
file: string;
|
|
13
|
+
size: number;
|
|
14
|
+
created_at: string;
|
|
15
|
+
items: number;
|
|
16
|
+
history: BackupRow[];
|
|
17
|
+
days_since_last: number | null;
|
|
18
|
+
}
|
|
19
|
+
export interface BackupListResult {
|
|
20
|
+
status: 'ok';
|
|
21
|
+
dir: string;
|
|
22
|
+
keep_n: number;
|
|
23
|
+
count: number;
|
|
24
|
+
history: BackupRow[];
|
|
25
|
+
days_since_last: number | null;
|
|
26
|
+
}
|
|
27
|
+
export interface RestoreResult {
|
|
28
|
+
status: 'ok';
|
|
29
|
+
restored_from: string;
|
|
30
|
+
safety_backup: string;
|
|
31
|
+
before_items: number;
|
|
32
|
+
items_total: number;
|
|
33
|
+
message: string;
|
|
34
|
+
}
|
|
35
|
+
/** 预告(`dryRun`)结果:只报「这份备份装了多少件、当前库多少件」,不落盘。 */
|
|
36
|
+
export interface RestorePreview {
|
|
37
|
+
status: 'ok';
|
|
38
|
+
dry_run: true;
|
|
39
|
+
restored_from: string;
|
|
40
|
+
items_in_backup: number | null;
|
|
41
|
+
items_current: number;
|
|
42
|
+
message: string;
|
|
43
|
+
}
|
|
44
|
+
export type RestoreOutcome = RestoreResult | RestorePreview;
|
|
45
|
+
export interface ExportResult {
|
|
46
|
+
status: 'ok';
|
|
47
|
+
file: string;
|
|
48
|
+
format: 'json' | 'csv';
|
|
49
|
+
size: number;
|
|
50
|
+
rows: number;
|
|
51
|
+
}
|
|
52
|
+
/** 备份目录名:配置 `backup.dir`,空串=默认(`backups`)。 */
|
|
53
|
+
export declare function backupDirName(): string;
|
|
54
|
+
/** 备份目录(库目录下 `backups/`)——设置页「备份目录」那一项的取值口;只算路径,不建目录。 */
|
|
55
|
+
export declare function resolveBackupDir(): string;
|
|
56
|
+
/** 备份:库快照(含 WAL)+ 清单打包成 zip,保留 N 份、删最旧;返回回执载荷。 */
|
|
57
|
+
export declare function createBackup(opts?: {
|
|
58
|
+
keepN?: number;
|
|
59
|
+
}): BackupResult;
|
|
60
|
+
/** 备份历史:现读盘,不缓存(面板/回执要的是当前真状态)。 */
|
|
61
|
+
export declare function listBackups(opts?: {
|
|
62
|
+
keepN?: number;
|
|
63
|
+
}): BackupListResult;
|
|
64
|
+
/**
|
|
65
|
+
* 导入恢复:拿备份里的 `home.db` 覆盖当前库;覆盖前先自备份一次(数据安全优先于便捷)。
|
|
66
|
+
* `dryRun`=预告支(SM8-4「文件选择(预告式)→ 校验 → 冲突预览 → 确认导入」的中间那一步):只校验+报数,不落盘。
|
|
67
|
+
*/
|
|
68
|
+
export declare function restoreBackup(file: string, opts?: {
|
|
69
|
+
keepN?: number;
|
|
70
|
+
dryRun?: boolean;
|
|
71
|
+
}): RestoreOutcome;
|
|
72
|
+
/** 导出:JSON=全表可迁移;CSV=物品 ⋈ 位置便携(列与老家 ops.py:620 逐列相同)。 */
|
|
73
|
+
export declare function exportData(opts?: {
|
|
74
|
+
format?: string;
|
|
75
|
+
output?: string;
|
|
76
|
+
}): ExportResult;
|
|
77
|
+
//# sourceMappingURL=backup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../src/fetch/backup.ts"],"names":[],"mappings":"AAkBA,qEAAqE;AACrE,eAAO,MAAM,uBAAuB,YAAY,CAAC;AAKjD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,IAAI,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,IAAI,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,+CAA+C;AAC/C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,IAAI,CAAC;IACb,OAAO,EAAE,IAAI,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,cAAc,CAAC;AAE5D,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,IAAI,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AA0BD,8CAA8C;AAC9C,wBAAgB,aAAa,IAAI,MAAM,CAGtC;AAED,yDAAyD;AACzD,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AA8BD,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,YAAY,CA0CxE;AAED,mCAAmC;AACnC,wBAAgB,WAAW,CAAC,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,gBAAgB,CAK3E;AAmBD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,cAAc,CAmD3G;AAaD,yDAAyD;AACzD,wBAAgB,UAAU,CAAC,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,YAAY,CA6CxF"}
|