@modusensus/dsh-mneme 0.8.13 → 0.8.15
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/LICENSE +21 -21
- package/README.md +655 -626
- package/assets/icon.svg +3 -3
- package/bin/cli.mjs +689 -689
- package/bin/dsh-mneme-mcp.mjs +510 -510
- package/bin/dsh-mneme-serve.mjs +151 -0
- package/cordis.patch.yml +21 -21
- package/docs/CONFIGURATION.md +263 -0
- package/docs/CONTINUITY.md +124 -0
- package/docs/DAEMON.md +46 -0
- package/docs/ENTITIES.md +245 -0
- package/docs/LOCAL_MODEL.md +222 -0
- package/docs/SEMANTIC.md +256 -0
- package/docs/SLEEP.md +164 -0
- package/docs/STORAGE.md +89 -0
- package/lib/api-standalone.js +673 -572
- package/lib/api.js +1437 -1433
- package/lib/bootstrap.js +211 -211
- package/lib/client.js +5444 -5295
- package/lib/commands.js +95 -95
- package/lib/config.js +880 -836
- package/lib/content-hash.js +54 -54
- package/lib/continuity.js +220 -220
- package/lib/document-index.js +94 -94
- package/lib/document.js +303 -303
- package/lib/dream/clustering.js +118 -118
- package/lib/dream/decisions.js +674 -674
- package/lib/dream/narratives.js +44 -44
- package/lib/dream/sleep.js +819 -819
- package/lib/dream.js +1501 -1501
- package/lib/embedding.js +177 -177
- package/lib/entities/extractor.js +252 -252
- package/lib/graph/anchoring.js +179 -179
- package/lib/guide.js +74 -74
- package/lib/heat.js +144 -144
- package/lib/hot-memory.js +46 -46
- package/lib/index.js +535 -671
- package/lib/inject.js +464 -450
- package/lib/lang.js +248 -229
- package/lib/local-embedder.js +358 -358
- package/lib/maintenance.js +142 -142
- package/lib/mirror.js +330 -330
- package/lib/organize.js +450 -450
- package/lib/peak-hours.js +117 -117
- package/lib/placement.js +13 -0
- package/lib/pre-inject-gate.js +340 -0
- package/lib/quality-filter.js +126 -126
- package/lib/recall-stats.js +175 -175
- package/lib/reranker.js +269 -269
- package/lib/runtime/adopt.js +176 -176
- package/lib/runtime/closure.js +172 -172
- package/lib/runtime/download.js +247 -247
- package/lib/runtime/layout.js +265 -265
- package/lib/runtime/loader.js +252 -252
- package/lib/runtime/model-fetch.js +361 -361
- package/lib/runtime/provision.js +237 -237
- package/lib/runtime/tarball.js +130 -130
- package/lib/runtime/verify.js +223 -204
- package/lib/scope.js +146 -146
- package/lib/search/adaptive.js +60 -60
- package/lib/search/bm25.js +96 -96
- package/lib/semantic.js +229 -0
- package/lib/sensitive-scan.js +209 -209
- package/lib/serve.js +215 -0
- package/lib/service.js +2663 -2596
- package/lib/settings.js +517 -509
- package/lib/store.js +3007 -3007
- package/lib/summarize.js +891 -856
- package/lib/tools.js +743 -737
- package/lib/vector-index.js +110 -110
- package/lib/version-check.js +122 -122
- package/lib/write-admission.js +402 -402
- package/locale/en.json +6 -6
- package/locale/zh.json +6 -6
- package/package.json +8 -4
- package/runtime-manifest.json +526 -526
- package/scripts/benchmark-embed.js +201 -201
- package/scripts/benchmark-recall.js +249 -249
- package/scripts/benchmark-rerank.js +166 -166
- package/scripts/build-runtime-manifest.mjs +224 -224
- package/scripts/changelog-prep.mjs +36 -0
- package/scripts/check-sync.js +42 -42
- package/scripts/e2e-dsh.js +220 -220
- package/scripts/mneme-runtime.mjs +277 -277
- package/scripts/stress-dsh.js +255 -255
- package/scripts/sync-lib.js +47 -47
- package/scripts/sync-test-badge.mjs +69 -69
- package/scripts/test-count-sync.mjs +44 -44
- package/src/api-standalone.js +673 -572
- package/src/api.js +1437 -1433
- package/src/bootstrap.js +211 -211
- package/src/commands.js +95 -95
- package/src/config.js +880 -836
- package/src/content-hash.js +54 -54
- package/src/continuity.js +220 -220
- package/src/document-index.js +94 -94
- package/src/document.js +303 -303
- package/src/dream/clustering.js +118 -118
- package/src/dream/decisions.js +674 -674
- package/src/dream/narratives.js +44 -44
- package/src/dream/sleep.js +819 -819
- package/src/dream.js +1501 -1501
- package/src/embedding.js +177 -177
- package/src/entities/extractor.js +252 -252
- package/src/graph/anchoring.js +179 -179
- package/src/guide.js +74 -74
- package/src/heat.js +144 -144
- package/src/hot-memory.js +46 -46
- package/src/index.js +535 -671
- package/src/inject.js +464 -450
- package/src/lang.js +248 -229
- package/src/local-embedder.js +358 -358
- package/src/maintenance.js +142 -142
- package/src/mirror.js +330 -330
- package/src/organize.js +450 -450
- package/src/peak-hours.js +117 -117
- package/src/placement.js +13 -0
- package/src/pre-inject-gate.js +340 -0
- package/src/quality-filter.js +126 -126
- package/src/recall-stats.js +175 -175
- package/src/reranker.js +269 -269
- package/src/runtime/adopt.js +176 -176
- package/src/runtime/closure.js +172 -172
- package/src/runtime/download.js +247 -247
- package/src/runtime/layout.js +265 -265
- package/src/runtime/loader.js +252 -252
- package/src/runtime/model-fetch.js +361 -361
- package/src/runtime/provision.js +237 -237
- package/src/runtime/tarball.js +130 -130
- package/src/runtime/verify.js +223 -204
- package/src/scope.js +146 -146
- package/src/search/adaptive.js +60 -60
- package/src/search/bm25.js +96 -96
- package/src/semantic.js +229 -0
- package/src/sensitive-scan.js +209 -209
- package/src/serve.js +215 -0
- package/src/service.js +2663 -2596
- package/src/settings.js +517 -509
- package/src/store.js +3007 -3007
- package/src/summarize.js +891 -856
- package/src/tools.js +743 -737
- package/src/vector-index.js +110 -110
- package/src/version-check.js +122 -122
- package/src/write-admission.js +402 -402
- package/test/adaptive-inject-budget.test.js +85 -85
- package/test/api-routes-gaps.test.js +218 -218
- package/test/api.test.js +1702 -1688
- package/test/audit.test.js +448 -448
- package/test/baseline-persist.test.js +248 -248
- package/test/benchmark.test.js +94 -94
- package/test/bootstrap.test.js +220 -220
- package/test/changelog-prep.test.js +60 -0
- package/test/client.test.js +1230 -1169
- package/test/clustering.test.js +100 -100
- package/test/commands.test.js +106 -106
- package/test/config.test.js +66 -66
- package/test/conflict-freeze.test.js +300 -300
- package/test/content-hash.test.js +204 -204
- package/test/continuity.test.js +333 -333
- package/test/document-dir.test.js +233 -233
- package/test/document.test.js +671 -671
- package/test/dream-archive-guardrail.test.js +116 -116
- package/test/dream-candidate-hybrid.test.js +281 -281
- package/test/dream-coverage-degrade.test.js +86 -86
- package/test/dream-failure-backoff.test.js +173 -173
- package/test/dream-peak-hours.test.js +194 -194
- package/test/dream.test.js +1385 -1383
- package/test/embedding-ready.test.js +196 -196
- package/test/entities.test.js +627 -547
- package/test/entity-recall.test.js +179 -179
- package/test/epistemic.test.js +325 -325
- package/test/fnew-0112.test.js +311 -311
- package/test/fnew-03.test.js +422 -422
- package/test/graph-anchoring.test.js +184 -184
- package/test/graph-api.test.js +175 -175
- package/test/graph-inject-budget.test.js +103 -103
- package/test/graph-passive-confirm.test.js +91 -91
- package/test/graph-weight-evolution.test.js +104 -104
- package/test/heat.test.js +175 -175
- package/test/helpers/dream-mock.js +82 -82
- package/test/helpers/peer-worker.mjs +25 -25
- package/test/helpers/runtime-source.js +60 -60
- package/test/helpers/tar-builder.js +80 -80
- package/test/helpers/write-admission-samples.js +308 -308
- package/test/hot-memory.test.js +145 -145
- package/test/inject-content-cap.test.js +91 -91
- package/test/inject-first-round-bm25.test.js +89 -89
- package/test/inject-heat.test.js +77 -61
- package/test/inject-parent-gate.test.js +106 -106
- package/test/inject-pools.test.js +194 -194
- package/test/inject-recall.test.js +105 -105
- package/test/inject-rotation.test.js +161 -161
- package/test/inject.test.js +420 -420
- package/test/lang.test.js +87 -87
- package/test/lastrunat-persist.test.js +101 -101
- package/test/lib-smoke.test.js +96 -96
- package/test/llm-audit.test.js +598 -598
- package/test/llm-message-source.test.js +207 -207
- package/test/local-embedder.test.js +292 -292
- package/test/maintenance.test.js +391 -391
- package/test/mcp-stdio.test.js +385 -385
- package/test/mirror-dirty.test.js +424 -424
- package/test/mirror-edit-digest.test.js +187 -187
- package/test/mirror-generation.test.js +499 -499
- package/test/mirror-types.test.js +208 -208
- package/test/mirror.test.js +249 -249
- package/test/narrative-bars.test.js +162 -162
- package/test/organize.test.js +418 -418
- package/test/peer-blockers.test.js +193 -193
- package/test/placement.test.js +36 -0
- package/test/policy-epoch.test.js +259 -259
- package/test/pre-inject-gate.test.js +434 -0
- package/test/quality-filter.test.js +186 -186
- package/test/reasoning-effort.test.js +752 -752
- package/test/recall-anti-update.test.js +82 -82
- package/test/recall-evals.test.js +253 -253
- package/test/recall-layer.test.js +326 -326
- package/test/recall-stats.test.js +189 -189
- package/test/receipt-chain.test.js +451 -451
- package/test/reflection.test.js +226 -226
- package/test/reindex-backfill.test.js +62 -62
- package/test/reranker-single-logit.test.js +73 -73
- package/test/reranker.test.js +197 -197
- package/test/resident-status.test.js +83 -83
- package/test/runtime-adopt.test.js +206 -206
- package/test/runtime-cli.test.js +89 -89
- package/test/runtime-closure.test.js +193 -193
- package/test/runtime-download.test.js +302 -302
- package/test/runtime-layout.test.js +163 -163
- package/test/runtime-loader.test.js +255 -255
- package/test/runtime-manifest.test.js +159 -159
- package/test/runtime-model-fetch.test.js +348 -348
- package/test/runtime-provision.test.js +101 -101
- package/test/runtime-tarball.test.js +81 -81
- package/test/runtime-verify.test.js +319 -279
- package/test/scope-candidates.test.js +239 -239
- package/test/scope-explicit.test.js +452 -452
- package/test/scope-inject-soft.test.js +106 -106
- package/test/scope-retrieval.test.js +197 -197
- package/test/scope-storage.test.js +255 -255
- package/test/scope-strict.test.js +367 -343
- package/test/search-fusion.test.js +90 -90
- package/test/semantic.test.js +124 -124
- package/test/sensitive-scan.test.js +207 -207
- package/test/serve-bin.test.js +121 -0
- package/test/serve.test.js +196 -0
- package/test/service-search.test.js +174 -174
- package/test/service.test.js +405 -405
- package/test/settings.test.js +261 -261
- package/test/skip-invalid-restore.test.js +262 -262
- package/test/sleep-action-set.test.js +422 -422
- package/test/sleep-heat.test.js +126 -126
- package/test/sleep-scheduler-rearm.test.js +89 -89
- package/test/sleep.test.js +527 -527
- package/test/standalone-api.test.js +751 -544
- package/test/store-vector-cache.test.js +98 -98
- package/test/store.test.js +396 -396
- package/test/stress.test.js +209 -209
- package/test/summarize-occurred-at.test.js +127 -0
- package/test/summarize-reasoning-effort.test.js +189 -189
- package/test/summarize.test.js +1465 -1465
- package/test/supersede-state-tracking.test.js +394 -0
- package/test/test-count-sync.test.js +60 -60
- package/test/tools-dto-schema-matrix.test.js +325 -325
- package/test/tools-memory-get-schema.test.js +65 -65
- package/test/tools.test.js +428 -374
- package/test/updated-at-semantics.test.js +113 -113
- package/test/vector-index.test.js +221 -221
- package/test/version-check.test.js +152 -152
- package/test/webServer-optional.test.js +82 -82
- package/test/write-admission.test.js +668 -668
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
// test/helpers/runtime-source.js
|
|
2
|
-
// 共享的「可收编源」夹具:CLI(scripts/mneme-runtime.mjs 的 adopt)与面板服务层
|
|
3
|
-
// (src/runtime/adopt-service.js)两处的测试要造同一棵树。放这里是为了不让两份漂移 ——
|
|
4
|
-
// 尤其是闭包必须能解出 onnxruntime-node / sharp,否则测的就不是「收编」这件事了。
|
|
5
|
-
|
|
6
|
-
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
|
|
7
|
-
import { tmpdir } from "node:os";
|
|
8
|
-
import { join } from "node:path";
|
|
9
|
-
|
|
10
|
-
/** 结构检查点名到「平台 + 架构」,所以夹具必须用本机平台,否则 CI 上必挂。 */
|
|
11
|
-
function writeNativeDir(nm) {
|
|
12
|
-
mkdirSync(join(nm, "onnxruntime-node", "bin", "napi-v6", process.platform, process.arch), { recursive: true });
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* 造一个最小可收编的 `<tmp>/node_modules`。
|
|
17
|
-
*
|
|
18
|
-
* transformers 必须把 onnxruntime-node / sharp 声明成自己的依赖,闭包计划才会收它们;
|
|
19
|
-
* 否则 payload 里不会有这两个包,结构检查会因为「缺必需包」失败,测的就不是收编了。
|
|
20
|
-
*
|
|
21
|
-
* `withMissingDep: true` 时再声明一个装不上的必需依赖:planClosure 会记一条 gap,
|
|
22
|
-
* 而 describePayload 只看那三个必需包 —— 这正是「结构说通过、闭包其实缺件」的场景。
|
|
23
|
-
* @param {{withMissingDep?: boolean}} [opts] - 选项。
|
|
24
|
-
* @returns {{base: string, nm: string, runtimeDir: string}} 临时根、源 node_modules、空白目标目录。
|
|
25
|
-
*/
|
|
26
|
-
export function makeSourceModules({ withMissingDep = false } = {}) {
|
|
27
|
-
const base = mkdtempSync(join(tmpdir(), "mneme-src-"));
|
|
28
|
-
const nm = join(base, "node_modules");
|
|
29
|
-
const write = (rel, body) => {
|
|
30
|
-
const full = join(nm, rel);
|
|
31
|
-
mkdirSync(join(full, ".."), { recursive: true });
|
|
32
|
-
writeFileSync(full, body);
|
|
33
|
-
};
|
|
34
|
-
const dependencies = {
|
|
35
|
-
"onnxruntime-node": "^1.24.3",
|
|
36
|
-
sharp: "^0.34.5",
|
|
37
|
-
...(withMissingDep ? { "definitely-not-installed-pkg": "^1.0.0" } : {})
|
|
38
|
-
};
|
|
39
|
-
write(
|
|
40
|
-
"@huggingface/transformers/package.json",
|
|
41
|
-
JSON.stringify({ name: "@huggingface/transformers", version: "4.2.0", dependencies })
|
|
42
|
-
);
|
|
43
|
-
write("@huggingface/transformers/dist/transformers.node.mjs", "export const x = 1;\n");
|
|
44
|
-
write("onnxruntime-node/package.json", JSON.stringify({ name: "onnxruntime-node", version: "1.24.3" }));
|
|
45
|
-
write("sharp/package.json", JSON.stringify({ name: "sharp", version: "0.34.5" }));
|
|
46
|
-
writeNativeDir(nm);
|
|
47
|
-
return { base, nm, runtimeDir: mkdtempSync(join(tmpdir(), "mneme-dst-")) };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* 空源:连 transformers 都没有。这是「profile 里根本没装」或 `--from` 指错目录时的真实输入,
|
|
52
|
-
* 也是曾经抛 TypeError 的那条路径。
|
|
53
|
-
* @returns {{base: string, nm: string, runtimeDir: string}}
|
|
54
|
-
*/
|
|
55
|
-
export function makeEmptyModules() {
|
|
56
|
-
const base = mkdtempSync(join(tmpdir(), "mneme-empty-"));
|
|
57
|
-
const nm = join(base, "node_modules");
|
|
58
|
-
mkdirSync(nm, { recursive: true });
|
|
59
|
-
return { base, nm, runtimeDir: mkdtempSync(join(tmpdir(), "mneme-dst-")) };
|
|
60
|
-
}
|
|
1
|
+
// test/helpers/runtime-source.js
|
|
2
|
+
// 共享的「可收编源」夹具:CLI(scripts/mneme-runtime.mjs 的 adopt)与面板服务层
|
|
3
|
+
// (src/runtime/adopt-service.js)两处的测试要造同一棵树。放这里是为了不让两份漂移 ——
|
|
4
|
+
// 尤其是闭包必须能解出 onnxruntime-node / sharp,否则测的就不是「收编」这件事了。
|
|
5
|
+
|
|
6
|
+
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
|
|
10
|
+
/** 结构检查点名到「平台 + 架构」,所以夹具必须用本机平台,否则 CI 上必挂。 */
|
|
11
|
+
function writeNativeDir(nm) {
|
|
12
|
+
mkdirSync(join(nm, "onnxruntime-node", "bin", "napi-v6", process.platform, process.arch), { recursive: true });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 造一个最小可收编的 `<tmp>/node_modules`。
|
|
17
|
+
*
|
|
18
|
+
* transformers 必须把 onnxruntime-node / sharp 声明成自己的依赖,闭包计划才会收它们;
|
|
19
|
+
* 否则 payload 里不会有这两个包,结构检查会因为「缺必需包」失败,测的就不是收编了。
|
|
20
|
+
*
|
|
21
|
+
* `withMissingDep: true` 时再声明一个装不上的必需依赖:planClosure 会记一条 gap,
|
|
22
|
+
* 而 describePayload 只看那三个必需包 —— 这正是「结构说通过、闭包其实缺件」的场景。
|
|
23
|
+
* @param {{withMissingDep?: boolean}} [opts] - 选项。
|
|
24
|
+
* @returns {{base: string, nm: string, runtimeDir: string}} 临时根、源 node_modules、空白目标目录。
|
|
25
|
+
*/
|
|
26
|
+
export function makeSourceModules({ withMissingDep = false } = {}) {
|
|
27
|
+
const base = mkdtempSync(join(tmpdir(), "mneme-src-"));
|
|
28
|
+
const nm = join(base, "node_modules");
|
|
29
|
+
const write = (rel, body) => {
|
|
30
|
+
const full = join(nm, rel);
|
|
31
|
+
mkdirSync(join(full, ".."), { recursive: true });
|
|
32
|
+
writeFileSync(full, body);
|
|
33
|
+
};
|
|
34
|
+
const dependencies = {
|
|
35
|
+
"onnxruntime-node": "^1.24.3",
|
|
36
|
+
sharp: "^0.34.5",
|
|
37
|
+
...(withMissingDep ? { "definitely-not-installed-pkg": "^1.0.0" } : {})
|
|
38
|
+
};
|
|
39
|
+
write(
|
|
40
|
+
"@huggingface/transformers/package.json",
|
|
41
|
+
JSON.stringify({ name: "@huggingface/transformers", version: "4.2.0", dependencies })
|
|
42
|
+
);
|
|
43
|
+
write("@huggingface/transformers/dist/transformers.node.mjs", "export const x = 1;\n");
|
|
44
|
+
write("onnxruntime-node/package.json", JSON.stringify({ name: "onnxruntime-node", version: "1.24.3" }));
|
|
45
|
+
write("sharp/package.json", JSON.stringify({ name: "sharp", version: "0.34.5" }));
|
|
46
|
+
writeNativeDir(nm);
|
|
47
|
+
return { base, nm, runtimeDir: mkdtempSync(join(tmpdir(), "mneme-dst-")) };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 空源:连 transformers 都没有。这是「profile 里根本没装」或 `--from` 指错目录时的真实输入,
|
|
52
|
+
* 也是曾经抛 TypeError 的那条路径。
|
|
53
|
+
* @returns {{base: string, nm: string, runtimeDir: string}}
|
|
54
|
+
*/
|
|
55
|
+
export function makeEmptyModules() {
|
|
56
|
+
const base = mkdtempSync(join(tmpdir(), "mneme-empty-"));
|
|
57
|
+
const nm = join(base, "node_modules");
|
|
58
|
+
mkdirSync(nm, { recursive: true });
|
|
59
|
+
return { base, nm, runtimeDir: mkdtempSync(join(tmpdir(), "mneme-dst-")) };
|
|
60
|
+
}
|
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
// test/helpers/tar-builder.js
|
|
2
|
-
// 共享的 tar 造件器:tarball 读取层与取件层的测试都要造归档,放这里免得两份漂移。
|
|
3
|
-
// 只造真东西(POSIX ustar 布局 + 正确的校验和),不引 tar 库 —— 那正是被测代码要回避的依赖。
|
|
4
|
-
|
|
5
|
-
import { gzipSync } from "node:zlib";
|
|
6
|
-
|
|
7
|
-
/** 一个 ustar 头块;字段布局照 POSIX,校验和按规范先按空格算再写回。 */
|
|
8
|
-
export function tarHeader({ name = "", prefix = "", size = 0, type = "0" }) {
|
|
9
|
-
const header = Buffer.alloc(512);
|
|
10
|
-
header.write(name, 0, 100, "utf8");
|
|
11
|
-
header.write("0000644\0", 100, 8, "utf8");
|
|
12
|
-
header.write("0000000\0", 108, 8, "utf8");
|
|
13
|
-
header.write("0000000\0", 116, 8, "utf8");
|
|
14
|
-
header.write(`${size.toString(8).padStart(11, "0")}\0`, 124, 12, "utf8");
|
|
15
|
-
header.write("00000000000\0", 136, 12, "utf8");
|
|
16
|
-
header.write(" ", 148, 8, "utf8");
|
|
17
|
-
header.write(type, 156, 1, "utf8");
|
|
18
|
-
header.write("ustar\0", 257, 6, "utf8");
|
|
19
|
-
header.write("00", 263, 2, "utf8");
|
|
20
|
-
header.write(prefix, 345, 155, "utf8");
|
|
21
|
-
let sum = 0;
|
|
22
|
-
for (const byte of header) sum += byte;
|
|
23
|
-
header.write(`${sum.toString(8).padStart(6, "0")}\0 `, 148, 8, "utf8");
|
|
24
|
-
return header;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/** 普通文件条目(数据按 512 对齐补齐)。 */
|
|
28
|
-
export function tarFile(name, body, { prefix = "" } = {}) {
|
|
29
|
-
const data = Buffer.from(body, "utf8");
|
|
30
|
-
const padded = Buffer.alloc(Math.ceil(data.length / 512) * 512);
|
|
31
|
-
data.copy(padded);
|
|
32
|
-
return [tarHeader({ name, prefix, size: data.length, type: "0" }), padded];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** 目录("5")/ 符号链接("2")等无数据条目。 */
|
|
36
|
-
export function tarMeta(name, type) {
|
|
37
|
-
return [tarHeader({ name, size: 0, type })];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** pax 扩展头:载荷是 `长度 path=值\n`。 */
|
|
41
|
-
export function tarPax(path) {
|
|
42
|
-
const record = Buffer.from(`path=${path}\n`, "utf8");
|
|
43
|
-
const line = `${record.length + String(record.length).length} path=${path}\n`;
|
|
44
|
-
return [tarHeader({ name: "PaxHeaders/x", size: Buffer.byteLength(line), type: "x" }), padTo512(Buffer.from(line, "utf8"))];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** 补齐到 512 的整数倍。 */
|
|
48
|
-
export function padTo512(buffer) {
|
|
49
|
-
if (buffer.length % 512 === 0) return buffer;
|
|
50
|
-
const padded = Buffer.alloc(Math.ceil(buffer.length / 512) * 512);
|
|
51
|
-
buffer.copy(padded);
|
|
52
|
-
return padded;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** 两个全零块 = 归档结束。 */
|
|
56
|
-
export const END_BLOCKS = [Buffer.alloc(512), Buffer.alloc(512)];
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 造一份 .tgz。`entries` 每项:
|
|
60
|
-
* { path, body } 普通文件(自动加 `package/` 前缀,除非 path 已含它)
|
|
61
|
-
* { path, type } 目录/符号链接等(type 是 ustar 的 typeflag 字符)
|
|
62
|
-
* { paxPath } pax 头,覆盖下一条目的路径
|
|
63
|
-
* @param {Array<object>} entries - 条目。
|
|
64
|
-
* @param {{prefix?: string|null, end?: boolean}} [opts] - 前缀(默认 package/)、是否追加结束块。
|
|
65
|
-
* @returns {Buffer} gzip 后的归档。
|
|
66
|
-
*/
|
|
67
|
-
export function makeTgz(entries, { prefix = "package/", end = true } = {}) {
|
|
68
|
-
const blocks = [];
|
|
69
|
-
for (const entry of entries) {
|
|
70
|
-
if (entry.paxPath !== undefined) {
|
|
71
|
-
blocks.push(...tarPax(prefix === null ? entry.paxPath : `${prefix}${entry.paxPath}`));
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
const path = prefix === null || entry.path.startsWith(prefix) ? entry.path : `${prefix}${entry.path}`;
|
|
75
|
-
if (entry.type !== undefined) blocks.push(...tarMeta(path, entry.type));
|
|
76
|
-
else blocks.push(...tarFile(path, entry.body ?? ""));
|
|
77
|
-
}
|
|
78
|
-
if (end) blocks.push(...END_BLOCKS);
|
|
79
|
-
return gzipSync(Buffer.concat(blocks));
|
|
80
|
-
}
|
|
1
|
+
// test/helpers/tar-builder.js
|
|
2
|
+
// 共享的 tar 造件器:tarball 读取层与取件层的测试都要造归档,放这里免得两份漂移。
|
|
3
|
+
// 只造真东西(POSIX ustar 布局 + 正确的校验和),不引 tar 库 —— 那正是被测代码要回避的依赖。
|
|
4
|
+
|
|
5
|
+
import { gzipSync } from "node:zlib";
|
|
6
|
+
|
|
7
|
+
/** 一个 ustar 头块;字段布局照 POSIX,校验和按规范先按空格算再写回。 */
|
|
8
|
+
export function tarHeader({ name = "", prefix = "", size = 0, type = "0" }) {
|
|
9
|
+
const header = Buffer.alloc(512);
|
|
10
|
+
header.write(name, 0, 100, "utf8");
|
|
11
|
+
header.write("0000644\0", 100, 8, "utf8");
|
|
12
|
+
header.write("0000000\0", 108, 8, "utf8");
|
|
13
|
+
header.write("0000000\0", 116, 8, "utf8");
|
|
14
|
+
header.write(`${size.toString(8).padStart(11, "0")}\0`, 124, 12, "utf8");
|
|
15
|
+
header.write("00000000000\0", 136, 12, "utf8");
|
|
16
|
+
header.write(" ", 148, 8, "utf8");
|
|
17
|
+
header.write(type, 156, 1, "utf8");
|
|
18
|
+
header.write("ustar\0", 257, 6, "utf8");
|
|
19
|
+
header.write("00", 263, 2, "utf8");
|
|
20
|
+
header.write(prefix, 345, 155, "utf8");
|
|
21
|
+
let sum = 0;
|
|
22
|
+
for (const byte of header) sum += byte;
|
|
23
|
+
header.write(`${sum.toString(8).padStart(6, "0")}\0 `, 148, 8, "utf8");
|
|
24
|
+
return header;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** 普通文件条目(数据按 512 对齐补齐)。 */
|
|
28
|
+
export function tarFile(name, body, { prefix = "" } = {}) {
|
|
29
|
+
const data = Buffer.from(body, "utf8");
|
|
30
|
+
const padded = Buffer.alloc(Math.ceil(data.length / 512) * 512);
|
|
31
|
+
data.copy(padded);
|
|
32
|
+
return [tarHeader({ name, prefix, size: data.length, type: "0" }), padded];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** 目录("5")/ 符号链接("2")等无数据条目。 */
|
|
36
|
+
export function tarMeta(name, type) {
|
|
37
|
+
return [tarHeader({ name, size: 0, type })];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** pax 扩展头:载荷是 `长度 path=值\n`。 */
|
|
41
|
+
export function tarPax(path) {
|
|
42
|
+
const record = Buffer.from(`path=${path}\n`, "utf8");
|
|
43
|
+
const line = `${record.length + String(record.length).length} path=${path}\n`;
|
|
44
|
+
return [tarHeader({ name: "PaxHeaders/x", size: Buffer.byteLength(line), type: "x" }), padTo512(Buffer.from(line, "utf8"))];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** 补齐到 512 的整数倍。 */
|
|
48
|
+
export function padTo512(buffer) {
|
|
49
|
+
if (buffer.length % 512 === 0) return buffer;
|
|
50
|
+
const padded = Buffer.alloc(Math.ceil(buffer.length / 512) * 512);
|
|
51
|
+
buffer.copy(padded);
|
|
52
|
+
return padded;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** 两个全零块 = 归档结束。 */
|
|
56
|
+
export const END_BLOCKS = [Buffer.alloc(512), Buffer.alloc(512)];
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 造一份 .tgz。`entries` 每项:
|
|
60
|
+
* { path, body } 普通文件(自动加 `package/` 前缀,除非 path 已含它)
|
|
61
|
+
* { path, type } 目录/符号链接等(type 是 ustar 的 typeflag 字符)
|
|
62
|
+
* { paxPath } pax 头,覆盖下一条目的路径
|
|
63
|
+
* @param {Array<object>} entries - 条目。
|
|
64
|
+
* @param {{prefix?: string|null, end?: boolean}} [opts] - 前缀(默认 package/)、是否追加结束块。
|
|
65
|
+
* @returns {Buffer} gzip 后的归档。
|
|
66
|
+
*/
|
|
67
|
+
export function makeTgz(entries, { prefix = "package/", end = true } = {}) {
|
|
68
|
+
const blocks = [];
|
|
69
|
+
for (const entry of entries) {
|
|
70
|
+
if (entry.paxPath !== undefined) {
|
|
71
|
+
blocks.push(...tarPax(prefix === null ? entry.paxPath : `${prefix}${entry.paxPath}`));
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const path = prefix === null || entry.path.startsWith(prefix) ? entry.path : `${prefix}${entry.path}`;
|
|
75
|
+
if (entry.type !== undefined) blocks.push(...tarMeta(path, entry.type));
|
|
76
|
+
else blocks.push(...tarFile(path, entry.body ?? ""));
|
|
77
|
+
}
|
|
78
|
+
if (end) blocks.push(...END_BLOCKS);
|
|
79
|
+
return gzipSync(Buffer.concat(blocks));
|
|
80
|
+
}
|