@chainlesschain/personal-data-hub 0.4.29 → 0.4.31
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/lib/forensics/qq-nt-collect.js +190 -0
- package/lib/prompt-builder.js +15 -1
- package/package.json +8 -3
- package/__tests__/adapter-guide.test.js +0 -47
- package/__tests__/adapter-spec.test.js +0 -78
- package/__tests__/adapters/ai-chat-cookie-capture-spec.test.js +0 -211
- package/__tests__/adapters/ai-chat-health-checker.test.js +0 -262
- package/__tests__/adapters/ai-chat-history.test.js +0 -396
- package/__tests__/adapters/ai-chat-http-client.test.js +0 -242
- package/__tests__/adapters/ai-chat-vendors.test.js +0 -874
- package/__tests__/adapters/alipay-bill-adapter.test.js +0 -538
- package/__tests__/adapters/apple-health.test.js +0 -95
- package/__tests__/adapters/bank-family.test.js +0 -125
- package/__tests__/adapters/biz-tianyancha.test.js +0 -159
- package/__tests__/adapters/browser-history-chrome.test.js +0 -377
- package/__tests__/adapters/browser-history-edge.test.js +0 -159
- package/__tests__/adapters/car-mercedesme.test.js +0 -74
- package/__tests__/adapters/doc-baidu-netdisk.test.js +0 -102
- package/__tests__/adapters/doc-camscanner.test.js +0 -147
- package/__tests__/adapters/doc-platforms.test.js +0 -177
- package/__tests__/adapters/edu-huawei-learning-live.test.js +0 -198
- package/__tests__/adapters/edu-zuoyebang-live.test.js +0 -226
- package/__tests__/adapters/email-adapter-snapshot.test.js +0 -237
- package/__tests__/adapters/email-adapter.test.js +0 -742
- package/__tests__/adapters/email-classifier.test.js +0 -347
- package/__tests__/adapters/email-imap-session.test.js +0 -334
- package/__tests__/adapters/email-parser.test.js +0 -244
- package/__tests__/adapters/email-pdf-extractor.test.js +0 -529
- package/__tests__/adapters/email-providers.test.js +0 -84
- package/__tests__/adapters/email-retry-progress.test.js +0 -294
- package/__tests__/adapters/email-templates.test.js +0 -822
- package/__tests__/adapters/family-23-collectors-scaffold.test.js +0 -182
- package/__tests__/adapters/finance-alipay-live.test.js +0 -258
- package/__tests__/adapters/finance-dcep.test.js +0 -74
- package/__tests__/adapters/fitness-joyrun.test.js +0 -82
- package/__tests__/adapters/game-genshin-live.test.js +0 -238
- package/__tests__/adapters/game-genshin-scaffold.test.js +0 -108
- package/__tests__/adapters/game-honor-of-kings-live.test.js +0 -230
- package/__tests__/adapters/git-activity.test.js +0 -222
- package/__tests__/adapters/gov-12123.test.js +0 -103
- package/__tests__/adapters/gov-ixiamen.test.js +0 -150
- package/__tests__/adapters/gov-tax.test.js +0 -135
- package/__tests__/adapters/health-meiyou.test.js +0 -125
- package/__tests__/adapters/local-files.test.js +0 -264
- package/__tests__/adapters/local-im-pc.test.js +0 -154
- package/__tests__/adapters/messaging-whatsapp.test.js +0 -289
- package/__tests__/adapters/music-kugou.test.js +0 -187
- package/__tests__/adapters/music-qq.test.js +0 -112
- package/__tests__/adapters/netease-music-live.test.js +0 -244
- package/__tests__/adapters/netease-music.test.js +0 -74
- package/__tests__/adapters/pc-local-discovery.test.js +0 -141
- package/__tests__/adapters/qq-pc-direct-read.test.js +0 -227
- package/__tests__/adapters/reading-family.test.js +0 -108
- package/__tests__/adapters/recruit-boss.test.js +0 -180
- package/__tests__/adapters/shell-history.test.js +0 -180
- package/__tests__/adapters/shopping-base.test.js +0 -179
- package/__tests__/adapters/shopping-dianping.test.js +0 -239
- package/__tests__/adapters/social-bilibili-adb-api-client.test.js +0 -721
- package/__tests__/adapters/social-bilibili-adb-chromium-cookies-reader.test.js +0 -346
- package/__tests__/adapters/social-bilibili-adb-collector.test.js +0 -284
- package/__tests__/adapters/social-bilibili-adb-cookies-extension.test.js +0 -343
- package/__tests__/adapters/social-bilibili-adb-snapshot-builder.test.js +0 -296
- package/__tests__/adapters/social-csdn.test.js +0 -175
- package/__tests__/adapters/social-dongchedi.test.js +0 -165
- package/__tests__/adapters/social-douyin-adb-aweme-detail.test.js +0 -165
- package/__tests__/adapters/social-douyin-adb-collector.test.js +0 -254
- package/__tests__/adapters/social-douyin-adb-db-extension.test.js +0 -114
- package/__tests__/adapters/social-douyin-adb-im-db-parser.test.js +0 -304
- package/__tests__/adapters/social-douyin-adb-snapshot-builder.test.js +0 -216
- package/__tests__/adapters/social-douyin-adb-usage-profile.test.js +0 -229
- package/__tests__/adapters/social-douyin-adb-watch-history.test.js +0 -269
- package/__tests__/adapters/social-kuaishou-adb-api-client.test.js +0 -496
- package/__tests__/adapters/social-kuaishou-adb-collector.test.js +0 -276
- package/__tests__/adapters/social-kuaishou-adb-cookies-extension.test.js +0 -152
- package/__tests__/adapters/social-kuaishou-adb-snapshot-builder.test.js +0 -178
- package/__tests__/adapters/social-toutiao-adb-account-reader.test.js +0 -135
- package/__tests__/adapters/social-toutiao-adb-api-client.test.js +0 -626
- package/__tests__/adapters/social-toutiao-adb-article.test.js +0 -155
- package/__tests__/adapters/social-toutiao-adb-collector.test.js +0 -378
- package/__tests__/adapters/social-toutiao-adb-cookies-extension.test.js +0 -193
- package/__tests__/adapters/social-toutiao-adb-snapshot-builder.test.js +0 -196
- package/__tests__/adapters/social-toutiao-kuaishou-scaffold.test.js +0 -311
- package/__tests__/adapters/social-weibo-adb-api-client.test.js +0 -362
- package/__tests__/adapters/social-weibo-adb-collector.test.js +0 -201
- package/__tests__/adapters/social-weibo-adb-cookies-extension.test.js +0 -167
- package/__tests__/adapters/social-weibo-adb-snapshot-builder.test.js +0 -189
- package/__tests__/adapters/social-xiaohongshu-adb-api-client.test.js +0 -431
- package/__tests__/adapters/social-xiaohongshu-adb-collector.test.js +0 -207
- package/__tests__/adapters/social-xiaohongshu-adb-cookies-extension.test.js +0 -0
- package/__tests__/adapters/social-xiaohongshu-adb-sign-provider-injection.test.js +0 -351
- package/__tests__/adapters/social-xiaohongshu-adb-sign.test.js +0 -130
- package/__tests__/adapters/social-xiaohongshu-adb-snapshot-builder.test.js +0 -200
- package/__tests__/adapters/social-zhihu.test.js +0 -246
- package/__tests__/adapters/system-data-adapter.test.js +0 -443
- package/__tests__/adapters/system-data-android-ingest.test.js +0 -144
- package/__tests__/adapters/system-data-android.test.js +0 -519
- package/__tests__/adapters/system-data-disclosure.test.js +0 -153
- package/__tests__/adapters/travel-12306.test.js +0 -512
- package/__tests__/adapters/travel-amap.test.js +0 -219
- package/__tests__/adapters/travel-baidu-map.test.js +0 -305
- package/__tests__/adapters/travel-base.test.js +0 -205
- package/__tests__/adapters/travel-ctrip.test.js +0 -377
- package/__tests__/adapters/travel-didi-consumer.test.js +0 -66
- package/__tests__/adapters/travel-didi.test.js +0 -204
- package/__tests__/adapters/travel-tencent-map.test.js +0 -207
- package/__tests__/adapters/travel-tongcheng.test.js +0 -289
- package/__tests__/adapters/video-platforms.test.js +0 -152
- package/__tests__/adapters/video-xigua.test.js +0 -106
- package/__tests__/adapters/vscode.test.js +0 -299
- package/__tests__/adapters/wechat-bootstrap.test.js +0 -240
- package/__tests__/adapters/wechat-env-probe.test.js +0 -162
- package/__tests__/adapters/wechat-frida-agent.test.js +0 -322
- package/__tests__/adapters/wechat-frida-integration.test.js +0 -149
- package/__tests__/adapters/wechat-frida-key-provider.test.js +0 -188
- package/__tests__/adapters/wechat-md5-key-provider.test.js +0 -101
- package/__tests__/adapters/wechat-pc-direct-read.test.js +0 -365
- package/__tests__/adapters/wechat-pc-group-topic.test.js +0 -63
- package/__tests__/adapters/wechat-pc-v4-sidecar.test.js +0 -72
- package/__tests__/adapters/weread.test.js +0 -123
- package/__tests__/adapters/wework-pc.test.js +0 -124
- package/__tests__/adapters/win-recent.test.js +0 -192
- package/__tests__/analysis-skills.test.js +0 -754
- package/__tests__/analysis.test.js +0 -1845
- package/__tests__/audio-ximalaya-snapshot.test.js +0 -279
- package/__tests__/batch.test.js +0 -133
- package/__tests__/bridges-cc-kg.test.js +0 -231
- package/__tests__/bridges-cc-llm.test.js +0 -191
- package/__tests__/bridges-cc-rag.test.js +0 -162
- package/__tests__/categories.test.js +0 -92
- package/__tests__/e2e/ai-chat-cross-source-journey.test.js +0 -213
- package/__tests__/e2e/full-user-journey.test.js +0 -188
- package/__tests__/e2e/local-data-adapters-cli.e2e.test.js +0 -146
- package/__tests__/entity-resolver-ingest-hook.test.js +0 -177
- package/__tests__/entity-resolver-stages.test.js +0 -411
- package/__tests__/entity-resolver-vault.test.js +0 -249
- package/__tests__/entity-resolver.test.js +0 -526
- package/__tests__/fitness-keep-snapshot.test.js +0 -224
- package/__tests__/fixtures/entity-resolver-200-mock.json +0 -96
- package/__tests__/ids.test.js +0 -45
- package/__tests__/integration/ai-chat-history-registry.test.js +0 -228
- package/__tests__/integration/aichat-wizard-end-to-end.test.js +0 -282
- package/__tests__/integration/cross-adapter-pipelines.test.js +0 -396
- package/__tests__/integration/local-data-adapters-pipeline.test.js +0 -373
- package/__tests__/integration/social-bilibili-pipeline.test.js +0 -261
- package/__tests__/integration/wechat-bootstrap-end-to-end.test.js +0 -390
- package/__tests__/key-providers.test.js +0 -126
- package/__tests__/kg-derive.test.js +0 -219
- package/__tests__/llm-client.test.js +0 -122
- package/__tests__/longtail-adapters.test.js +0 -281
- package/__tests__/messaging-qq-snapshot.test.js +0 -294
- package/__tests__/mobile-extractor-encrypted.test.js +0 -460
- package/__tests__/mobile-extractor.test.js +0 -288
- package/__tests__/mock-adapter.test.js +0 -93
- package/__tests__/prompt-builder.test.js +0 -249
- package/__tests__/query-parser.test.js +0 -365
- package/__tests__/rag-derive.test.js +0 -169
- package/__tests__/registry-readiness.test.js +0 -292
- package/__tests__/registry.test.js +0 -420
- package/__tests__/salvage-ingest.test.js +0 -97
- package/__tests__/schemas.test.js +0 -331
- package/__tests__/shopping-adapters.test.js +0 -392
- package/__tests__/shopping-eleme-snapshot.test.js +0 -454
- package/__tests__/shopping-pinduoduo-snapshot.test.js +0 -484
- package/__tests__/shopping-snapshot.test.js +0 -438
- package/__tests__/shopping-vipshop-snapshot.test.js +0 -425
- package/__tests__/shopping-xianyu-snapshot.test.js +0 -451
- package/__tests__/sidecar-contacts-cross-validate.test.js +0 -186
- package/__tests__/sidecar-supervisor.test.js +0 -128
- package/__tests__/sign-providers.test.js +0 -62
- package/__tests__/social-adapters.test.js +0 -280
- package/__tests__/social-bilibili-snapshot.test.js +0 -278
- package/__tests__/social-douban-snapshot.test.js +0 -351
- package/__tests__/social-douyin-im-direct-read.test.js +0 -377
- package/__tests__/social-douyin-salvage-collector.test.js +0 -98
- package/__tests__/social-douyin-salvage-mapper.test.js +0 -90
- package/__tests__/social-douyin-snapshot.test.js +0 -256
- package/__tests__/social-kuaishou-snapshot.test.js +0 -362
- package/__tests__/social-toutiao-snapshot.test.js +0 -366
- package/__tests__/social-weibo-snapshot.test.js +0 -234
- package/__tests__/social-weibo-sqlite-device.test.js +0 -174
- package/__tests__/social-xiaohongshu-snapshot.test.js +0 -232
- package/__tests__/sqlite-leaf-salvage.test.js +0 -97
- package/__tests__/travel-adapters.test.js +0 -483
- package/__tests__/travel-maps-snapshot.test.js +0 -426
- package/__tests__/vault-driver-error.test.js +0 -74
- package/__tests__/vault-search-helpers.test.js +0 -104
- package/__tests__/vault-search.test.js +0 -423
- package/__tests__/vault.test.js +0 -767
- package/__tests__/wechat-adapter.test.js +0 -594
- package/__tests__/whatsapp-adapter.test.js +0 -138
- package/scripts/_make-fixture-all.js +0 -126
- package/scripts/_make-fixture-contacts.js +0 -84
- package/scripts/evaluate-entity-resolver.js +0 -213
- package/scripts/run-native-tests-sandbox.sh +0 -55
- package/scripts/smoke-phase-5-5.js +0 -196
- package/scripts/smoke-phase-5-7.js +0 -181
- package/scripts/smoke-system-data-contacts.js +0 -309
- package/scripts/smoke-system-data.js +0 -312
- package/vitest.config.js +0 -88
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* AdapterRegistry.readiness() — the "why can't I collect" surface.
|
|
5
|
-
*
|
|
6
|
-
* Uses a STUB vault (readiness only calls vault.getWatermark, defensively)
|
|
7
|
-
* so this file does NOT depend on the native SQLCipher driver and runs on
|
|
8
|
-
* every host — unlike registry.test.js which opens a real LocalVault and is
|
|
9
|
-
* auto-skipped when bs3mc's ABI doesn't match the host Node. See
|
|
10
|
-
* vitest.config.js NATIVE_DEPENDENT_TESTS.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { describe, it, expect } from "vitest";
|
|
14
|
-
|
|
15
|
-
const fs = require("node:fs");
|
|
16
|
-
const os = require("node:os");
|
|
17
|
-
const path = require("node:path");
|
|
18
|
-
|
|
19
|
-
const { AdapterRegistry } = require("../lib/registry");
|
|
20
|
-
const {
|
|
21
|
-
READINESS_CATEGORY,
|
|
22
|
-
READINESS_STATUS,
|
|
23
|
-
} = require("../lib/adapter-readiness");
|
|
24
|
-
const { BilibiliAdapter } = require("../lib/adapters/social-bilibili");
|
|
25
|
-
const { TelegramAdapter } = require("../lib/adapters/messaging-telegram");
|
|
26
|
-
const { Train12306Adapter } = require("../lib/adapters/travel-12306");
|
|
27
|
-
const { EmailAdapter } = require("../lib/adapters/email-imap");
|
|
28
|
-
const { WechatAdapter } = require("../lib/adapters/wechat");
|
|
29
|
-
|
|
30
|
-
// ─── Stub vault — readiness() only needs getWatermark ─────────────────────
|
|
31
|
-
|
|
32
|
-
function stubVault(watermarks = {}) {
|
|
33
|
-
return {
|
|
34
|
-
_wm: watermarks,
|
|
35
|
-
getWatermark(adapter /*, scope */) {
|
|
36
|
-
return this._wm[adapter] || null;
|
|
37
|
-
},
|
|
38
|
-
audit() {},
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function byName(reports, name) {
|
|
43
|
-
return reports.find((r) => r.name === name);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
describe("AdapterRegistry.readiness()", () => {
|
|
47
|
-
it("snapshot adapter with no input → needs_setup / NO_INPUT", async () => {
|
|
48
|
-
const reg = new AdapterRegistry({ vault: stubVault() });
|
|
49
|
-
reg.register(new BilibiliAdapter());
|
|
50
|
-
const [r] = await reg.readiness();
|
|
51
|
-
expect(r.name).toBe("social-bilibili");
|
|
52
|
-
expect(r.ready).toBe(false);
|
|
53
|
-
expect(r.status).toBe(READINESS_STATUS.NEEDS_SETUP);
|
|
54
|
-
expect(r.reason).toBe("NO_INPUT");
|
|
55
|
-
expect(r.category).toBe(READINESS_CATEGORY.SNAPSHOT);
|
|
56
|
-
expect(typeof r.message).toBe("string");
|
|
57
|
-
expect(r.message.length).toBeGreaterThan(0);
|
|
58
|
-
expect(r.actionHint).toBeTruthy();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it("device-pull adapter (telegram) → needs_setup / DB_NOT_PULLED / device", async () => {
|
|
62
|
-
const reg = new AdapterRegistry({ vault: stubVault() });
|
|
63
|
-
reg.register(new TelegramAdapter());
|
|
64
|
-
const [r] = await reg.readiness();
|
|
65
|
-
expect(r.ready).toBe(false);
|
|
66
|
-
expect(r.reason).toBe("DB_NOT_PULLED");
|
|
67
|
-
expect(r.category).toBe(READINESS_CATEGORY.DEVICE);
|
|
68
|
-
expect(r.extractMode).toBe("device-pull");
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("12306 snapshot adapter → needs_setup", async () => {
|
|
72
|
-
const reg = new AdapterRegistry({ vault: stubVault() });
|
|
73
|
-
reg.register(new Train12306Adapter());
|
|
74
|
-
const [r] = await reg.readiness();
|
|
75
|
-
expect(r.ready).toBe(false);
|
|
76
|
-
expect(r.reason).toBe("NO_INPUT");
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it("email snapshot stub → NO_INPUT (no live IMAP login)", async () => {
|
|
80
|
-
const reg = new AdapterRegistry({ vault: stubVault() });
|
|
81
|
-
reg.register(new EmailAdapter({ snapshotMode: true }));
|
|
82
|
-
const [r] = await reg.readiness();
|
|
83
|
-
expect(r.ready).toBe(false);
|
|
84
|
-
expect(r.reason).toBe("NO_INPUT");
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it("email per-account → ready=configured WITHOUT opening an IMAP session", async () => {
|
|
88
|
-
let sessionFactoryCalled = false;
|
|
89
|
-
const adapter = new EmailAdapter({
|
|
90
|
-
account: { email: "user@gmail.com", authCode: "secret", provider: "gmail" },
|
|
91
|
-
// If readiness wrongly performed a live login it would call this.
|
|
92
|
-
sessionFactory: () => {
|
|
93
|
-
sessionFactoryCalled = true;
|
|
94
|
-
return { connect: async () => {}, close: async () => {} };
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
const reg = new AdapterRegistry({ vault: stubVault() });
|
|
98
|
-
reg.register(adapter);
|
|
99
|
-
const [r] = await reg.readiness();
|
|
100
|
-
expect(r.ready).toBe(true);
|
|
101
|
-
expect(r.status).toBe(READINESS_STATUS.READY);
|
|
102
|
-
expect(r.mode).toBe("configured");
|
|
103
|
-
expect(sessionFactoryCalled).toBe(false);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("wechat readiness with db+keyProvider present → configured WITHOUT calling getKey", async () => {
|
|
107
|
-
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "pdh-rd-wx-"));
|
|
108
|
-
const dbPath = path.join(tmp, "EnMicroMsg.db");
|
|
109
|
-
fs.writeFileSync(dbPath, "x");
|
|
110
|
-
let getKeyCalled = false;
|
|
111
|
-
const adapter = new WechatAdapter({
|
|
112
|
-
account: { uin: "12345" },
|
|
113
|
-
dbPath,
|
|
114
|
-
keyProvider: {
|
|
115
|
-
getKey: async () => {
|
|
116
|
-
getKeyCalled = true;
|
|
117
|
-
return "deadbeef";
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
});
|
|
121
|
-
const reg = new AdapterRegistry({ vault: stubVault() });
|
|
122
|
-
reg.register(adapter);
|
|
123
|
-
const [r] = await reg.readiness();
|
|
124
|
-
expect(r.ready).toBe(true);
|
|
125
|
-
expect(r.mode).toBe("configured");
|
|
126
|
-
// The whole point of readinessOnly: don't invoke the (frida) key provider.
|
|
127
|
-
expect(getKeyCalled).toBe(false);
|
|
128
|
-
fs.rmSync(tmp, { recursive: true, force: true });
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it("wechat with no db → DB_NOT_PULLED", async () => {
|
|
132
|
-
const adapter = new WechatAdapter({ account: { uin: "1" } });
|
|
133
|
-
const reg = new AdapterRegistry({ vault: stubVault() });
|
|
134
|
-
reg.register(adapter);
|
|
135
|
-
const [r] = await reg.readiness();
|
|
136
|
-
expect(r.ready).toBe(false);
|
|
137
|
-
expect(r.reason).toBe("DB_NOT_PULLED");
|
|
138
|
-
expect(r.category).toBe(READINESS_CATEGORY.DEVICE);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it("a hanging authenticate() hits the per-adapter timeout → PROBE_TIMEOUT", async () => {
|
|
142
|
-
const reg = new AdapterRegistry({ vault: stubVault() });
|
|
143
|
-
reg.register({
|
|
144
|
-
name: "hang-test",
|
|
145
|
-
version: "1.0.0",
|
|
146
|
-
capabilities: [],
|
|
147
|
-
dataDisclosure: { fields: [], sensitivity: "low" },
|
|
148
|
-
authenticate: () => new Promise(() => {}), // never resolves
|
|
149
|
-
healthCheck: async () => ({ ok: true }),
|
|
150
|
-
normalize: (r) => r,
|
|
151
|
-
// eslint-disable-next-line require-yield
|
|
152
|
-
sync: async function* () {},
|
|
153
|
-
});
|
|
154
|
-
const [r] = await reg.readiness({ timeoutMs: 200 });
|
|
155
|
-
expect(r.ready).toBe(false);
|
|
156
|
-
expect(r.reason).toBe("PROBE_TIMEOUT");
|
|
157
|
-
expect(r.status).toBe(READINESS_STATUS.ERROR);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
it("an unknown reason code falls back to UNKNOWN (never crashes)", async () => {
|
|
161
|
-
const reg = new AdapterRegistry({ vault: stubVault() });
|
|
162
|
-
reg.register({
|
|
163
|
-
name: "weird",
|
|
164
|
-
version: "1.0.0",
|
|
165
|
-
capabilities: [],
|
|
166
|
-
dataDisclosure: { fields: [], sensitivity: "low" },
|
|
167
|
-
authenticate: async () => ({ ok: false, reason: "TOTALLY_NEW_CODE_42" }),
|
|
168
|
-
healthCheck: async () => ({ ok: true }),
|
|
169
|
-
normalize: (r) => r,
|
|
170
|
-
// eslint-disable-next-line require-yield
|
|
171
|
-
sync: async function* () {},
|
|
172
|
-
});
|
|
173
|
-
const [r] = await reg.readiness();
|
|
174
|
-
expect(r.ready).toBe(false);
|
|
175
|
-
expect(r.reason).toBe("TOTALLY_NEW_CODE_42");
|
|
176
|
-
expect(r.message).toBeTruthy(); // mapped via UNKNOWN fallback
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it("folds last sync outcome from the watermark into the report", async () => {
|
|
180
|
-
const reg = new AdapterRegistry({
|
|
181
|
-
vault: stubVault({
|
|
182
|
-
"social-bilibili": {
|
|
183
|
-
last_synced_at: 1700000000000,
|
|
184
|
-
last_status: "error",
|
|
185
|
-
last_error: "boom from last run",
|
|
186
|
-
},
|
|
187
|
-
}),
|
|
188
|
-
});
|
|
189
|
-
reg.register(new BilibiliAdapter());
|
|
190
|
-
const [r] = await reg.readiness();
|
|
191
|
-
expect(r.lastSyncedAt).toBe(1700000000000);
|
|
192
|
-
expect(r.lastStatus).toBe("error");
|
|
193
|
-
expect(r.lastError).toBe("boom from last run");
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it("attaches a step-by-step import guide to each report", async () => {
|
|
197
|
-
const reg = new AdapterRegistry({ vault: stubVault() });
|
|
198
|
-
reg.register(new BilibiliAdapter());
|
|
199
|
-
reg.register(new WechatAdapter({ account: { uin: "1" } }));
|
|
200
|
-
const reports = await reg.readiness();
|
|
201
|
-
const bili = byName(reports, "social-bilibili");
|
|
202
|
-
expect(bili.guide).toBeTruthy();
|
|
203
|
-
expect(bili.guide.displayName).toBe("哔哩哔哩");
|
|
204
|
-
expect(Array.isArray(bili.guide.methods)).toBe(true);
|
|
205
|
-
expect(bili.guide.methods.length).toBeGreaterThan(0);
|
|
206
|
-
expect(bili.guide.methods[0].steps.length).toBeGreaterThan(0);
|
|
207
|
-
// wechat gets the bespoke device override, not the generic category guide
|
|
208
|
-
const wx = byName(reports, "wechat");
|
|
209
|
-
expect(wx.guide.displayName).toBe("微信(手机)");
|
|
210
|
-
expect(wx.guide.methods[0].label).toMatch(/frida|root/);
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it("reports every registered adapter in registration order", async () => {
|
|
214
|
-
const reg = new AdapterRegistry({ vault: stubVault() });
|
|
215
|
-
reg.register(new BilibiliAdapter());
|
|
216
|
-
reg.register(new TelegramAdapter());
|
|
217
|
-
reg.register(new Train12306Adapter());
|
|
218
|
-
const reports = await reg.readiness();
|
|
219
|
-
expect(reports.map((r) => r.name)).toEqual([
|
|
220
|
-
"social-bilibili",
|
|
221
|
-
"messaging-telegram",
|
|
222
|
-
"travel-12306",
|
|
223
|
-
]);
|
|
224
|
-
// every report carries the required UI fields
|
|
225
|
-
for (const r of reports) {
|
|
226
|
-
expect(r).toHaveProperty("ready");
|
|
227
|
-
expect(r).toHaveProperty("status");
|
|
228
|
-
expect(r).toHaveProperty("category");
|
|
229
|
-
expect(r).toHaveProperty("message");
|
|
230
|
-
}
|
|
231
|
-
expect(byName(reports, "messaging-telegram").reason).toBe("DB_NOT_PULLED");
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
describe("AdapterRegistry.readiness() — ADB one-click (social)", () => {
|
|
236
|
-
const oneClick = { oneClickNames: new Set(["social-bilibili"]) };
|
|
237
|
-
|
|
238
|
-
it("device connected → ready via adb-oneclick", async () => {
|
|
239
|
-
const reg = new AdapterRegistry({
|
|
240
|
-
vault: stubVault(),
|
|
241
|
-
adbReadiness: { ...oneClick, probe: async () => ({ deviceConnected: true, serial: "ABC123" }) },
|
|
242
|
-
});
|
|
243
|
-
reg.register(new BilibiliAdapter());
|
|
244
|
-
const [r] = await reg.readiness();
|
|
245
|
-
expect(r.ready).toBe(true);
|
|
246
|
-
expect(r.status).toBe(READINESS_STATUS.READY);
|
|
247
|
-
expect(r.mode).toBe("adb-oneclick");
|
|
248
|
-
expect(r.category).toBe(READINESS_CATEGORY.DEVICE);
|
|
249
|
-
expect(r.message).toMatch(/一键采集/);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it("no device → ADB_DEVICE_NEEDED (actionable, not the snapshot message)", async () => {
|
|
253
|
-
const reg = new AdapterRegistry({
|
|
254
|
-
vault: stubVault(),
|
|
255
|
-
adbReadiness: { ...oneClick, probe: async () => ({ deviceConnected: false }) },
|
|
256
|
-
});
|
|
257
|
-
reg.register(new BilibiliAdapter());
|
|
258
|
-
const [r] = await reg.readiness();
|
|
259
|
-
expect(r.ready).toBe(false);
|
|
260
|
-
expect(r.reason).toBe("ADB_DEVICE_NEEDED");
|
|
261
|
-
expect(r.category).toBe(READINESS_CATEGORY.DEVICE);
|
|
262
|
-
expect(r.message).toMatch(/root|USB|手机/);
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
it("a probe that throws degrades to ADB_DEVICE_NEEDED (never crashes)", async () => {
|
|
266
|
-
const reg = new AdapterRegistry({
|
|
267
|
-
vault: stubVault(),
|
|
268
|
-
adbReadiness: { ...oneClick, probe: async () => { throw new Error("adb missing"); } },
|
|
269
|
-
});
|
|
270
|
-
reg.register(new BilibiliAdapter());
|
|
271
|
-
const [r] = await reg.readiness();
|
|
272
|
-
expect(r.reason).toBe("ADB_DEVICE_NEEDED");
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
it("non-one-click adapter is unaffected by ADB readiness", async () => {
|
|
276
|
-
const reg = new AdapterRegistry({
|
|
277
|
-
vault: stubVault(),
|
|
278
|
-
adbReadiness: { oneClickNames: new Set(["social-bilibili"]), probe: async () => ({ deviceConnected: true }) },
|
|
279
|
-
});
|
|
280
|
-
reg.register(new TelegramAdapter());
|
|
281
|
-
const [r] = await reg.readiness();
|
|
282
|
-
expect(r.name).toBe("messaging-telegram");
|
|
283
|
-
expect(r.reason).toBe("DB_NOT_PULLED"); // unchanged
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
it("without adbReadiness config, social adapter still reports NO_INPUT", async () => {
|
|
287
|
-
const reg = new AdapterRegistry({ vault: stubVault() });
|
|
288
|
-
reg.register(new BilibiliAdapter());
|
|
289
|
-
const [r] = await reg.readiness();
|
|
290
|
-
expect(r.reason).toBe("NO_INPUT");
|
|
291
|
-
});
|
|
292
|
-
});
|