@testmuai/evidence-cli 0.1.1
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 +201 -0
- package/README.md +124 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +55 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.js +71 -0
- package/dist/config.js.map +1 -0
- package/dist/contract.d.ts +66 -0
- package/dist/contract.js +50 -0
- package/dist/contract.js.map +1 -0
- package/dist/diagnostics.d.ts +3 -0
- package/dist/diagnostics.js +11 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/finalize/index.d.ts +21 -0
- package/dist/finalize/index.js +196 -0
- package/dist/finalize/index.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/pack/byte-source.d.ts +33 -0
- package/dist/pack/byte-source.js +50 -0
- package/dist/pack/byte-source.js.map +1 -0
- package/dist/pack/container.d.ts +58 -0
- package/dist/pack/container.js +215 -0
- package/dist/pack/container.js.map +1 -0
- package/dist/pack/remote.d.ts +49 -0
- package/dist/pack/remote.js +258 -0
- package/dist/pack/remote.js.map +1 -0
- package/dist/report/reporter.d.ts +22 -0
- package/dist/report/reporter.js +66 -0
- package/dist/report/reporter.js.map +1 -0
- package/dist/schemas/0.1/L0/result.schema.json +150 -0
- package/dist/schemas/0.1/L0/run.schema.json +114 -0
- package/dist/schemas/0.1/L1/logs-meta.schema.json +39 -0
- package/dist/schemas/0.1/L1/video.schema.json +16 -0
- package/dist/schemas/compile.d.ts +11 -0
- package/dist/schemas/compile.js +45 -0
- package/dist/schemas/compile.js.map +1 -0
- package/dist/schemas/registry.d.ts +11 -0
- package/dist/schemas/registry.js +40 -0
- package/dist/schemas/registry.js.map +1 -0
- package/dist/validate/checks.d.ts +15 -0
- package/dist/validate/checks.js +152 -0
- package/dist/validate/checks.js.map +1 -0
- package/dist/validate/index.d.ts +5 -0
- package/dist/validate/index.js +99 -0
- package/dist/validate/index.js.map +1 -0
- package/dist/validate/l1.d.ts +12 -0
- package/dist/validate/l1.js +117 -0
- package/dist/validate/l1.js.map +1 -0
- package/dist/yaml.d.ts +4 -0
- package/dist/yaml.js +16 -0
- package/dist/yaml.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.finalize = finalize;
|
|
40
|
+
exports.sweepIncomplete = sweepIncomplete;
|
|
41
|
+
const node_fs_1 = require("node:fs");
|
|
42
|
+
const path = __importStar(require("node:path"));
|
|
43
|
+
const node_crypto_1 = require("node:crypto");
|
|
44
|
+
const adm_zip_1 = __importDefault(require("adm-zip"));
|
|
45
|
+
const yaml_1 = require("../yaml");
|
|
46
|
+
async function finalize(dir, opts) {
|
|
47
|
+
const stat = await node_fs_1.promises.stat(dir).catch(() => null);
|
|
48
|
+
if (!stat || !stat.isDirectory()) {
|
|
49
|
+
const e = new Error("finalize requires the live <name>.evidence/ directory, not a sealed zip");
|
|
50
|
+
e.code = "USAGE";
|
|
51
|
+
throw e;
|
|
52
|
+
}
|
|
53
|
+
const testsDir = path.join(dir, "tests");
|
|
54
|
+
const testIds = (await node_fs_1.promises.readdir(testsDir, { withFileTypes: true }).catch(() => []))
|
|
55
|
+
.filter((e) => e.isDirectory())
|
|
56
|
+
.map((e) => e.name)
|
|
57
|
+
.sort();
|
|
58
|
+
const totals = { tests: 0, passed: 0, failed: 0, broken: 0, skipped: 0 };
|
|
59
|
+
// Derive totals + write each definition.sha256 back into result.yaml.
|
|
60
|
+
for (const id of testIds) {
|
|
61
|
+
const resultPath = path.join(testsDir, id, "result.yaml");
|
|
62
|
+
const raw = await node_fs_1.promises.readFile(resultPath, "utf8");
|
|
63
|
+
const obj = (0, yaml_1.parseYaml)(raw);
|
|
64
|
+
totals.tests++;
|
|
65
|
+
const s = obj?.status;
|
|
66
|
+
if (s === "passed" || s === "failed" || s === "broken" || s === "skipped")
|
|
67
|
+
totals[s]++;
|
|
68
|
+
const defPath = obj?.definition?.path;
|
|
69
|
+
if (typeof defPath === "string" && defPath.length > 0) {
|
|
70
|
+
const bytes = await node_fs_1.promises.readFile(path.join(testsDir, id, defPath));
|
|
71
|
+
const hash = `sha256:${(0, node_crypto_1.createHash)("sha256").update(bytes).digest("hex")}`;
|
|
72
|
+
const doc = (0, yaml_1.parseDoc)(raw);
|
|
73
|
+
doc.setIn(["definition", "sha256"], hash);
|
|
74
|
+
await node_fs_1.promises.writeFile(resultPath, (0, yaml_1.stringifyDoc)(doc), "utf8");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Write derived run-level fields back, preserving producer formatting.
|
|
78
|
+
const runPath = path.join(dir, "run.yaml");
|
|
79
|
+
const runDoc = (0, yaml_1.parseDoc)(await node_fs_1.promises.readFile(runPath, "utf8"));
|
|
80
|
+
runDoc.setIn(["status"], "finalized");
|
|
81
|
+
runDoc.setIn(["ended"], opts.endedAt);
|
|
82
|
+
runDoc.setIn(["totals"], totals);
|
|
83
|
+
await node_fs_1.promises.writeFile(runPath, (0, yaml_1.stringifyDoc)(runDoc), "utf8");
|
|
84
|
+
// Seal: build the flat zip in memory, then swap it into the directory's place
|
|
85
|
+
// ATOMICALLY (decision 0042): fsynced sibling temp → rename dir aside → rename
|
|
86
|
+
// temp into place → best-effort parent fsync → remove aside. A complete copy of
|
|
87
|
+
// the pack exists at every instant, so no crash can lose or truncate it.
|
|
88
|
+
const zip = new adm_zip_1.default();
|
|
89
|
+
await addContents(zip, dir, "");
|
|
90
|
+
const buffer = zip.toBuffer();
|
|
91
|
+
const parent = path.dirname(dir);
|
|
92
|
+
const baseName = path.basename(dir); // <name>.evidence
|
|
93
|
+
const sealedPath = dir; // same path; the directory becomes a file
|
|
94
|
+
const rand = (0, node_crypto_1.randomBytes)(6).toString("hex");
|
|
95
|
+
const tmpPath = path.join(parent, `${baseName}.tmp-${rand}`);
|
|
96
|
+
const bakPath = path.join(parent, `${baseName}.bak-${rand}`);
|
|
97
|
+
const fh = await node_fs_1.promises.open(tmpPath, "w");
|
|
98
|
+
try {
|
|
99
|
+
await fh.writeFile(buffer);
|
|
100
|
+
await fh.sync(); // durable temp bytes before the rename (power-loss tier)
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
await fh.close();
|
|
104
|
+
}
|
|
105
|
+
await node_fs_1.promises.rename(dir, bakPath); // move the live directory aside (atomic)
|
|
106
|
+
await node_fs_1.promises.rename(tmpPath, sealedPath); // install the sealed file (atomic)
|
|
107
|
+
await fsyncDir(parent); // persist the directory-entry changes (best-effort)
|
|
108
|
+
await node_fs_1.promises.rm(bakPath, { recursive: true, force: true }); // cleanup (non-critical)
|
|
109
|
+
return { totals, sealedPath };
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* fsync a directory fd so its entry changes survive power loss. Best-effort:
|
|
113
|
+
* syncing a directory is a POSIX-ism (fine on Linux/macOS, unsupported on
|
|
114
|
+
* Windows), so failure is swallowed — it never makes the seal fail.
|
|
115
|
+
*/
|
|
116
|
+
async function fsyncDir(dir) {
|
|
117
|
+
try {
|
|
118
|
+
const dfd = await node_fs_1.promises.open(dir, "r");
|
|
119
|
+
try {
|
|
120
|
+
await dfd.sync();
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
await dfd.close();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// best-effort
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Recover leftovers from an interrupted atomic seal (decision 0042). The host
|
|
132
|
+
* calls this at startup over the directory that holds its packs; evidence-cli
|
|
133
|
+
* itself runs no daemon. After it returns, every pack is either a complete sealed
|
|
134
|
+
* file or a live directory — never a partial. A `.bak-*` is restored to the live
|
|
135
|
+
* directory when the sealed file is absent (else deleted as redundant); a
|
|
136
|
+
* `.tmp-*` is always deleted, since a re-`finalize` regenerates it deterministically.
|
|
137
|
+
*/
|
|
138
|
+
async function sweepIncomplete(parentDir) {
|
|
139
|
+
const restored = [];
|
|
140
|
+
const removed = [];
|
|
141
|
+
let entries;
|
|
142
|
+
try {
|
|
143
|
+
entries = await node_fs_1.promises.readdir(parentDir);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return { restored, removed };
|
|
147
|
+
}
|
|
148
|
+
// .bak first (may restore a live dir), then .tmp.
|
|
149
|
+
for (const entry of entries) {
|
|
150
|
+
const m = entry.match(/^(.+\.evidence)\.bak-[0-9a-f]+$/);
|
|
151
|
+
if (!m)
|
|
152
|
+
continue;
|
|
153
|
+
const base = m[1];
|
|
154
|
+
const basePath = path.join(parentDir, base);
|
|
155
|
+
const bakPath = path.join(parentDir, entry);
|
|
156
|
+
if (await pathExists(basePath)) {
|
|
157
|
+
await node_fs_1.promises.rm(bakPath, { recursive: true, force: true });
|
|
158
|
+
removed.push(entry);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
await node_fs_1.promises.rename(bakPath, basePath);
|
|
162
|
+
restored.push(base);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
for (const entry of entries) {
|
|
166
|
+
if (!/\.evidence\.tmp-[0-9a-f]+$/.test(entry))
|
|
167
|
+
continue;
|
|
168
|
+
await node_fs_1.promises.rm(path.join(parentDir, entry), { force: true });
|
|
169
|
+
removed.push(entry);
|
|
170
|
+
}
|
|
171
|
+
return { restored, removed };
|
|
172
|
+
}
|
|
173
|
+
async function pathExists(p) {
|
|
174
|
+
try {
|
|
175
|
+
await node_fs_1.promises.stat(p);
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/** Add a directory's contents to the zip flat (no wrapping folder entry). */
|
|
183
|
+
async function addContents(zip, dir, prefix) {
|
|
184
|
+
const entries = await node_fs_1.promises.readdir(dir, { withFileTypes: true });
|
|
185
|
+
for (const e of entries) {
|
|
186
|
+
const abs = path.join(dir, e.name);
|
|
187
|
+
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
188
|
+
if (e.isDirectory()) {
|
|
189
|
+
await addContents(zip, abs, rel);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
zip.addFile(rel, await node_fs_1.promises.readFile(abs));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/finalize/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { validate } from "./validate";
|
|
2
|
+
export type { ValidateOptions } from "./validate";
|
|
3
|
+
export { finalize, sweepIncomplete } from "./finalize";
|
|
4
|
+
export type { FinalizeOptions, SweepResult } from "./finalize";
|
|
5
|
+
export { loadConfig, resolveProfile, configPath } from "./config";
|
|
6
|
+
export type { EvidenceConfig } from "./config";
|
|
7
|
+
export * from "./contract";
|
|
8
|
+
export { openContainer, DirectoryContainer, ZipContainer, } from "./pack/container";
|
|
9
|
+
export type { PackContainer, DirEntry } from "./pack/container";
|
|
10
|
+
export { RemoteZipContainer, openRemoteZip } from "./pack/remote";
|
|
11
|
+
export { FileByteSource } from "./pack/byte-source";
|
|
12
|
+
export type { ByteSource } from "./pack/byte-source";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.FileByteSource = exports.openRemoteZip = exports.RemoteZipContainer = exports.ZipContainer = exports.DirectoryContainer = exports.openContainer = exports.configPath = exports.resolveProfile = exports.loadConfig = exports.sweepIncomplete = exports.finalize = exports.validate = void 0;
|
|
18
|
+
var validate_1 = require("./validate");
|
|
19
|
+
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return validate_1.validate; } });
|
|
20
|
+
var finalize_1 = require("./finalize");
|
|
21
|
+
Object.defineProperty(exports, "finalize", { enumerable: true, get: function () { return finalize_1.finalize; } });
|
|
22
|
+
Object.defineProperty(exports, "sweepIncomplete", { enumerable: true, get: function () { return finalize_1.sweepIncomplete; } });
|
|
23
|
+
var config_1 = require("./config");
|
|
24
|
+
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_1.loadConfig; } });
|
|
25
|
+
Object.defineProperty(exports, "resolveProfile", { enumerable: true, get: function () { return config_1.resolveProfile; } });
|
|
26
|
+
Object.defineProperty(exports, "configPath", { enumerable: true, get: function () { return config_1.configPath; } });
|
|
27
|
+
__exportStar(require("./contract"), exports);
|
|
28
|
+
var container_1 = require("./pack/container");
|
|
29
|
+
Object.defineProperty(exports, "openContainer", { enumerable: true, get: function () { return container_1.openContainer; } });
|
|
30
|
+
Object.defineProperty(exports, "DirectoryContainer", { enumerable: true, get: function () { return container_1.DirectoryContainer; } });
|
|
31
|
+
Object.defineProperty(exports, "ZipContainer", { enumerable: true, get: function () { return container_1.ZipContainer; } });
|
|
32
|
+
var remote_1 = require("./pack/remote");
|
|
33
|
+
Object.defineProperty(exports, "RemoteZipContainer", { enumerable: true, get: function () { return remote_1.RemoteZipContainer; } });
|
|
34
|
+
Object.defineProperty(exports, "openRemoteZip", { enumerable: true, get: function () { return remote_1.openRemoteZip; } });
|
|
35
|
+
var byte_source_1 = require("./pack/byte-source");
|
|
36
|
+
Object.defineProperty(exports, "FileByteSource", { enumerable: true, get: function () { return byte_source_1.FileByteSource; } });
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,uCAAsC;AAA7B,oGAAA,QAAQ,OAAA;AAEjB,uCAAuD;AAA9C,oGAAA,QAAQ,OAAA;AAAE,2GAAA,eAAe,OAAA;AAElC,mCAAkE;AAAzD,oGAAA,UAAU,OAAA;AAAE,wGAAA,cAAc,OAAA;AAAE,oGAAA,UAAU,OAAA;AAE/C,6CAA2B;AAC3B,8CAI0B;AAHxB,0GAAA,aAAa,OAAA;AACb,+GAAA,kBAAkB,OAAA;AAClB,yGAAA,YAAY,OAAA;AAGd,wCAAkE;AAAzD,4GAAA,kBAAkB,OAAA;AAAE,uGAAA,aAAa,OAAA;AAC1C,kDAAoD;AAA3C,6GAAA,cAAc,OAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A random-access, ranged byte source — the seam that lets a pack be read
|
|
3
|
+
* without downloading it whole (decision 0041). A local file, an HTTP server
|
|
4
|
+
* speaking Range, or a blob-store object all implement this identically; the
|
|
5
|
+
* RemoteZipContainer reads a zip's central directory and then only the entry
|
|
6
|
+
* byte-ranges it needs through this interface.
|
|
7
|
+
*/
|
|
8
|
+
export interface ByteSource {
|
|
9
|
+
/** Total length of the source in bytes. */
|
|
10
|
+
size(): Promise<number>;
|
|
11
|
+
/**
|
|
12
|
+
* Read `length` bytes starting at `offset`. Returns the bytes actually
|
|
13
|
+
* available (may be shorter than `length` only at EOF). `offset` is clamped
|
|
14
|
+
* to >= 0; a read fully past EOF yields an empty buffer.
|
|
15
|
+
*/
|
|
16
|
+
read(offset: number, length: number): Promise<Buffer>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A ByteSource backed by a local file, opened lazily and read with positional
|
|
20
|
+
* reads (never loading the whole file). Useful as the default source and as a
|
|
21
|
+
* stand-in for a blob object in tests.
|
|
22
|
+
*/
|
|
23
|
+
export declare class FileByteSource implements ByteSource {
|
|
24
|
+
private readonly path;
|
|
25
|
+
private handle;
|
|
26
|
+
private cachedSize;
|
|
27
|
+
constructor(path: string);
|
|
28
|
+
private open;
|
|
29
|
+
size(): Promise<number>;
|
|
30
|
+
read(offset: number, length: number): Promise<Buffer>;
|
|
31
|
+
/** Release the underlying file handle (no-op if never opened). */
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileByteSource = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
/**
|
|
6
|
+
* A ByteSource backed by a local file, opened lazily and read with positional
|
|
7
|
+
* reads (never loading the whole file). Useful as the default source and as a
|
|
8
|
+
* stand-in for a blob object in tests.
|
|
9
|
+
*/
|
|
10
|
+
class FileByteSource {
|
|
11
|
+
path;
|
|
12
|
+
handle = null;
|
|
13
|
+
cachedSize = null;
|
|
14
|
+
constructor(path) {
|
|
15
|
+
this.path = path;
|
|
16
|
+
}
|
|
17
|
+
async open() {
|
|
18
|
+
if (!this.handle)
|
|
19
|
+
this.handle = await node_fs_1.promises.open(this.path, "r");
|
|
20
|
+
return this.handle;
|
|
21
|
+
}
|
|
22
|
+
async size() {
|
|
23
|
+
if (this.cachedSize === null) {
|
|
24
|
+
this.cachedSize = (await node_fs_1.promises.stat(this.path)).size;
|
|
25
|
+
}
|
|
26
|
+
return this.cachedSize;
|
|
27
|
+
}
|
|
28
|
+
async read(offset, length) {
|
|
29
|
+
if (length <= 0)
|
|
30
|
+
return Buffer.alloc(0);
|
|
31
|
+
const total = await this.size();
|
|
32
|
+
const start = Math.max(0, Math.min(offset, total));
|
|
33
|
+
const want = Math.max(0, Math.min(length, total - start));
|
|
34
|
+
if (want === 0)
|
|
35
|
+
return Buffer.alloc(0);
|
|
36
|
+
const buf = Buffer.alloc(want);
|
|
37
|
+
const fh = await this.open();
|
|
38
|
+
const { bytesRead } = await fh.read(buf, 0, want, start);
|
|
39
|
+
return bytesRead === want ? buf : buf.subarray(0, bytesRead);
|
|
40
|
+
}
|
|
41
|
+
/** Release the underlying file handle (no-op if never opened). */
|
|
42
|
+
async close() {
|
|
43
|
+
if (this.handle) {
|
|
44
|
+
await this.handle.close();
|
|
45
|
+
this.handle = null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.FileByteSource = FileByteSource;
|
|
50
|
+
//# sourceMappingURL=byte-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"byte-source.js","sourceRoot":"","sources":["../../src/pack/byte-source.ts"],"names":[],"mappings":";;;AAAA,qCAAyC;AAoBzC;;;;GAIG;AACH,MAAa,cAAc;IAII;IAHrB,MAAM,GAAyB,IAAI,CAAC;IACpC,UAAU,GAAkB,IAAI,CAAC;IAEzC,YAA6B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAErC,KAAK,CAAC,IAAI;QAChB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,MAAM,GAAG,MAAM,kBAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YAC7B,IAAI,CAAC,UAAU,GAAG,CAAC,MAAM,kBAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QACpD,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAc;QACvC,IAAI,MAAM,IAAI,CAAC;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;QAC1D,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC7B,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACzD,OAAO,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAC/D,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACrB,CAAC;IACH,CAAC;CACF;AArCD,wCAqCC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** An immediate child of a pack directory, from listDir. */
|
|
2
|
+
export interface DirEntry {
|
|
3
|
+
name: string;
|
|
4
|
+
isDir: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface PackContainer {
|
|
7
|
+
kind: "directory" | "zip";
|
|
8
|
+
/** pack name = file/dir base name with the .evidence suffix stripped */
|
|
9
|
+
name: string;
|
|
10
|
+
readManifest(): Promise<string | null>;
|
|
11
|
+
listTestIds(): Promise<string[]>;
|
|
12
|
+
readResult(testId: string): Promise<string | null>;
|
|
13
|
+
fileExists(testId: string, relPath: string): Promise<boolean>;
|
|
14
|
+
readBytes(testId: string, relPath: string): Promise<Buffer | null>;
|
|
15
|
+
/** Does an entry (file or directory) exist at this pack-root-relative path? */
|
|
16
|
+
exists(rel: string): Promise<boolean>;
|
|
17
|
+
/** Is the pack-root-relative path a directory? */
|
|
18
|
+
isDir(rel: string): Promise<boolean>;
|
|
19
|
+
/** Immediate children of a pack-root-relative directory (sorted by name). */
|
|
20
|
+
listDir(rel: string): Promise<DirEntry[]>;
|
|
21
|
+
/** Read a pack-root-relative text file, or null if absent. */
|
|
22
|
+
readText(rel: string): Promise<string | null>;
|
|
23
|
+
}
|
|
24
|
+
export declare class DirectoryContainer implements PackContainer {
|
|
25
|
+
private readonly root;
|
|
26
|
+
readonly kind: "directory";
|
|
27
|
+
constructor(root: string);
|
|
28
|
+
get name(): string;
|
|
29
|
+
readManifest(): Promise<string | null>;
|
|
30
|
+
listTestIds(): Promise<string[]>;
|
|
31
|
+
readResult(testId: string): Promise<string | null>;
|
|
32
|
+
fileExists(testId: string, relPath: string): Promise<boolean>;
|
|
33
|
+
readBytes(testId: string, relPath: string): Promise<Buffer | null>;
|
|
34
|
+
exists(rel: string): Promise<boolean>;
|
|
35
|
+
isDir(rel: string): Promise<boolean>;
|
|
36
|
+
listDir(rel: string): Promise<DirEntry[]>;
|
|
37
|
+
readText(rel: string): Promise<string | null>;
|
|
38
|
+
}
|
|
39
|
+
export declare class ZipContainer implements PackContainer {
|
|
40
|
+
private readonly file;
|
|
41
|
+
readonly kind: "zip";
|
|
42
|
+
private readonly zip;
|
|
43
|
+
constructor(file: string);
|
|
44
|
+
get name(): string;
|
|
45
|
+
private readEntry;
|
|
46
|
+
readManifest(): Promise<string | null>;
|
|
47
|
+
listTestIds(): Promise<string[]>;
|
|
48
|
+
readResult(testId: string): Promise<string | null>;
|
|
49
|
+
fileExists(testId: string, relPath: string): Promise<boolean>;
|
|
50
|
+
readBytes(testId: string, relPath: string): Promise<Buffer | null>;
|
|
51
|
+
/** True if any entry sits under `<rel>/` — i.e. rel is a directory. */
|
|
52
|
+
private hasPrefix;
|
|
53
|
+
exists(rel: string): Promise<boolean>;
|
|
54
|
+
isDir(rel: string): Promise<boolean>;
|
|
55
|
+
listDir(rel: string): Promise<DirEntry[]>;
|
|
56
|
+
readText(rel: string): Promise<string | null>;
|
|
57
|
+
}
|
|
58
|
+
export declare function openContainer(target: string): Promise<PackContainer>;
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.ZipContainer = exports.DirectoryContainer = void 0;
|
|
40
|
+
exports.openContainer = openContainer;
|
|
41
|
+
const node_fs_1 = require("node:fs");
|
|
42
|
+
const path = __importStar(require("node:path"));
|
|
43
|
+
const adm_zip_1 = __importDefault(require("adm-zip"));
|
|
44
|
+
function stripEvidence(base) {
|
|
45
|
+
return base.replace(/\.evidence$/, "");
|
|
46
|
+
}
|
|
47
|
+
class DirectoryContainer {
|
|
48
|
+
root;
|
|
49
|
+
kind = "directory";
|
|
50
|
+
constructor(root) {
|
|
51
|
+
this.root = root;
|
|
52
|
+
}
|
|
53
|
+
get name() {
|
|
54
|
+
return stripEvidence(path.basename(this.root));
|
|
55
|
+
}
|
|
56
|
+
async readManifest() {
|
|
57
|
+
return readFileOrNull(path.join(this.root, "run.yaml"));
|
|
58
|
+
}
|
|
59
|
+
async listTestIds() {
|
|
60
|
+
try {
|
|
61
|
+
const entries = await node_fs_1.promises.readdir(path.join(this.root, "tests"), {
|
|
62
|
+
withFileTypes: true,
|
|
63
|
+
});
|
|
64
|
+
return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async readResult(testId) {
|
|
71
|
+
return readFileOrNull(path.join(this.root, "tests", testId, "result.yaml"));
|
|
72
|
+
}
|
|
73
|
+
async fileExists(testId, relPath) {
|
|
74
|
+
try {
|
|
75
|
+
await node_fs_1.promises.access(path.join(this.root, "tests", testId, relPath));
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async readBytes(testId, relPath) {
|
|
83
|
+
try {
|
|
84
|
+
return await node_fs_1.promises.readFile(path.join(this.root, "tests", testId, relPath));
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async exists(rel) {
|
|
91
|
+
try {
|
|
92
|
+
await node_fs_1.promises.access(path.join(this.root, rel));
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async isDir(rel) {
|
|
100
|
+
try {
|
|
101
|
+
return (await node_fs_1.promises.stat(path.join(this.root, rel))).isDirectory();
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async listDir(rel) {
|
|
108
|
+
try {
|
|
109
|
+
const entries = await node_fs_1.promises.readdir(path.join(this.root, rel), {
|
|
110
|
+
withFileTypes: true,
|
|
111
|
+
});
|
|
112
|
+
return entries
|
|
113
|
+
.map((e) => ({ name: e.name, isDir: e.isDirectory() }))
|
|
114
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async readText(rel) {
|
|
121
|
+
return readFileOrNull(path.join(this.root, rel));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
exports.DirectoryContainer = DirectoryContainer;
|
|
125
|
+
class ZipContainer {
|
|
126
|
+
file;
|
|
127
|
+
kind = "zip";
|
|
128
|
+
zip;
|
|
129
|
+
constructor(file) {
|
|
130
|
+
this.file = file;
|
|
131
|
+
this.zip = new adm_zip_1.default(file);
|
|
132
|
+
}
|
|
133
|
+
get name() {
|
|
134
|
+
return stripEvidence(path.basename(this.file));
|
|
135
|
+
}
|
|
136
|
+
readEntry(entry) {
|
|
137
|
+
const e = this.zip.getEntry(entry);
|
|
138
|
+
return e ? e.getData().toString("utf8") : null;
|
|
139
|
+
}
|
|
140
|
+
async readManifest() {
|
|
141
|
+
return this.readEntry("run.yaml");
|
|
142
|
+
}
|
|
143
|
+
async listTestIds() {
|
|
144
|
+
const ids = new Set();
|
|
145
|
+
for (const e of this.zip.getEntries()) {
|
|
146
|
+
const m = e.entryName.match(/^tests\/([^/]+)\//);
|
|
147
|
+
if (m)
|
|
148
|
+
ids.add(m[1]);
|
|
149
|
+
}
|
|
150
|
+
return [...ids].sort();
|
|
151
|
+
}
|
|
152
|
+
async readResult(testId) {
|
|
153
|
+
return this.readEntry(`tests/${testId}/result.yaml`);
|
|
154
|
+
}
|
|
155
|
+
async fileExists(testId, relPath) {
|
|
156
|
+
return this.zip.getEntry(`tests/${testId}/${relPath}`) != null;
|
|
157
|
+
}
|
|
158
|
+
async readBytes(testId, relPath) {
|
|
159
|
+
const e = this.zip.getEntry(`tests/${testId}/${relPath}`);
|
|
160
|
+
return e ? e.getData() : null;
|
|
161
|
+
}
|
|
162
|
+
/** True if any entry sits under `<rel>/` — i.e. rel is a directory. */
|
|
163
|
+
hasPrefix(rel) {
|
|
164
|
+
const prefix = rel.endsWith("/") ? rel : `${rel}/`;
|
|
165
|
+
return this.zip.getEntries().some((e) => e.entryName.startsWith(prefix));
|
|
166
|
+
}
|
|
167
|
+
async exists(rel) {
|
|
168
|
+
return this.zip.getEntry(rel) != null || this.hasPrefix(rel);
|
|
169
|
+
}
|
|
170
|
+
async isDir(rel) {
|
|
171
|
+
return this.hasPrefix(rel);
|
|
172
|
+
}
|
|
173
|
+
async listDir(rel) {
|
|
174
|
+
const prefix = rel === "" ? "" : rel.endsWith("/") ? rel : `${rel}/`;
|
|
175
|
+
const children = new Map(); // name -> isDir
|
|
176
|
+
for (const e of this.zip.getEntries()) {
|
|
177
|
+
if (!e.entryName.startsWith(prefix))
|
|
178
|
+
continue;
|
|
179
|
+
const rest = e.entryName.slice(prefix.length);
|
|
180
|
+
if (rest === "")
|
|
181
|
+
continue;
|
|
182
|
+
const slash = rest.indexOf("/");
|
|
183
|
+
if (slash === -1) {
|
|
184
|
+
if (!children.has(rest))
|
|
185
|
+
children.set(rest, false);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
children.set(rest.slice(0, slash), true);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return [...children.entries()]
|
|
192
|
+
.map(([name, isDir]) => ({ name, isDir }))
|
|
193
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
194
|
+
}
|
|
195
|
+
async readText(rel) {
|
|
196
|
+
const e = this.zip.getEntry(rel);
|
|
197
|
+
return e ? e.getData().toString("utf8") : null;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
exports.ZipContainer = ZipContainer;
|
|
201
|
+
async function openContainer(target) {
|
|
202
|
+
const stat = await node_fs_1.promises.stat(target);
|
|
203
|
+
return stat.isDirectory()
|
|
204
|
+
? new DirectoryContainer(target)
|
|
205
|
+
: new ZipContainer(target);
|
|
206
|
+
}
|
|
207
|
+
async function readFileOrNull(p) {
|
|
208
|
+
try {
|
|
209
|
+
return await node_fs_1.promises.readFile(p, "utf8");
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=container.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/pack/container.ts"],"names":[],"mappings":"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"}
|