@esposter/shared-node 4.1.2 → 4.2.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/package.json +4 -4
- package/dist/bench.d.ts +0 -5
- package/dist/bench.js +0 -10
- package/dist/cache.d.ts +0 -7
- package/dist/cache.js +0 -27
- package/dist/child-process.d.ts +0 -16
- package/dist/child-process.js +0 -17
- package/dist/execSync-CtM99iYq.js +0 -17
- package/dist/reporter.d.ts +0 -6
- package/dist/reporter.js +0 -133
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@esposter/shared-node",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "Node-only shared tooling: the machine-wide download cache, hidden-window child processes, and benchmark reporting reused across packages.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"benchmark",
|
|
@@ -52,10 +52,10 @@
|
|
|
52
52
|
"typecheck": "tsc"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@esposter/shared": "4.
|
|
55
|
+
"@esposter/shared": "4.2.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@esposter/configuration": "4.
|
|
58
|
+
"@esposter/configuration": "4.2.0",
|
|
59
59
|
"@types/node": "^26.6.5",
|
|
60
60
|
"tsdown": "^0.23.1"
|
|
61
61
|
},
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"optional": true
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "fef4971cf6a621a2c1850f32fcec19ee4ec0de99"
|
|
71
71
|
}
|
package/dist/bench.d.ts
DELETED
package/dist/bench.js
DELETED
package/dist/cache.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
//#region src/services/cache/constants.d.ts
|
|
2
|
-
export declare const CACHE_ROOT: string;
|
|
3
|
-
export declare const CONTENT_CACHE_DIRECTORY: string;
|
|
4
|
-
//#endregion
|
|
5
|
-
//#region src/services/cache/readContentAddressedObject.d.ts
|
|
6
|
-
export declare const readContentAddressedObject: (hash: string, download: () => Promise<Uint8Array>, directory?: string) => Promise<Buffer>;
|
|
7
|
-
//#endregion
|
package/dist/cache.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { InvalidOperationError, Operation, SITE_NAME, getResultAsync, noop } from "@esposter/shared";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { createHash } from "node:crypto";
|
|
5
|
-
import { existsSync } from "node:fs";
|
|
6
|
-
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
7
|
-
//#region src/services/cache/constants.ts
|
|
8
|
-
const CACHE_ROOT = join(homedir(), SITE_NAME, "cache");
|
|
9
|
-
const CONTENT_CACHE_DIRECTORY = join(CACHE_ROOT, "content");
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/services/cache/readContentAddressedObject.ts
|
|
12
|
-
const readContentAddressedObject = async (hash, download, directory = CONTENT_CACHE_DIRECTORY) => {
|
|
13
|
-
const path = join(directory, hash);
|
|
14
|
-
if (existsSync(path)) return readFile(path);
|
|
15
|
-
const bytes = Buffer.from(await download());
|
|
16
|
-
if (createHash("sha256").update(bytes).digest("hex") !== hash) throw new InvalidOperationError(Operation.Read, hash, "does not hash to its name");
|
|
17
|
-
await mkdir(directory, { recursive: true });
|
|
18
|
-
const temporaryPath = `${path}.${crypto.randomUUID()}.part`;
|
|
19
|
-
await writeFile(temporaryPath, bytes);
|
|
20
|
-
await getResultAsync(() => rename(temporaryPath, path)).match(noop, async (error) => {
|
|
21
|
-
await rm(temporaryPath, { force: true });
|
|
22
|
-
if (!existsSync(path)) throw error;
|
|
23
|
-
});
|
|
24
|
-
return bytes;
|
|
25
|
-
};
|
|
26
|
-
//#endregion
|
|
27
|
-
export { CACHE_ROOT, CONTENT_CACHE_DIRECTORY, readContentAddressedObject };
|
package/dist/child-process.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { execFile as execFile$1, execFileSync as execFileSync$1, execSync as execSync$1, spawn as spawn$1, spawnSync as spawnSync$1 } from "node:child_process";
|
|
2
|
-
//#region src/services/childProcess/execFile.d.ts
|
|
3
|
-
export declare const execFile: typeof execFile$1;
|
|
4
|
-
//#endregion
|
|
5
|
-
//#region src/services/childProcess/execFileSync.d.ts
|
|
6
|
-
export declare const execFileSync: typeof execFileSync$1;
|
|
7
|
-
//#endregion
|
|
8
|
-
//#region src/services/childProcess/execSync.d.ts
|
|
9
|
-
export declare const execSync: typeof execSync$1;
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/services/childProcess/spawn.d.ts
|
|
12
|
-
export declare const spawn: typeof spawn$1;
|
|
13
|
-
//#endregion
|
|
14
|
-
//#region src/services/childProcess/spawnSync.d.ts
|
|
15
|
-
export declare const spawnSync: typeof spawnSync$1;
|
|
16
|
-
//#endregion
|
package/dist/child-process.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { n as withHiddenWindow, t as execSync } from "./execSync-CtM99iYq.js";
|
|
2
|
-
import { execFile as execFile$1, execFileSync as execFileSync$1, spawn as spawn$1, spawnSync as spawnSync$1 } from "node:child_process";
|
|
3
|
-
import { promisify } from "node:util";
|
|
4
|
-
//#region src/services/childProcess/execFile.ts
|
|
5
|
-
const execFile = ((file, ...parameters) => execFile$1(file, ...withHiddenWindow(parameters)));
|
|
6
|
-
Object.defineProperty(execFile, promisify.custom, { value: (file, ...parameters) => promisify(execFile$1)(file, ...withHiddenWindow(parameters)) });
|
|
7
|
-
//#endregion
|
|
8
|
-
//#region src/services/childProcess/execFileSync.ts
|
|
9
|
-
const execFileSync = ((file, ...parameters) => execFileSync$1(file, ...withHiddenWindow(parameters)));
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/services/childProcess/spawn.ts
|
|
12
|
-
const spawn = ((file, ...parameters) => spawn$1(file, ...withHiddenWindow(parameters)));
|
|
13
|
-
//#endregion
|
|
14
|
-
//#region src/services/childProcess/spawnSync.ts
|
|
15
|
-
const spawnSync = ((file, ...parameters) => spawnSync$1(file, ...withHiddenWindow(parameters)));
|
|
16
|
-
//#endregion
|
|
17
|
-
export { execFile, execFileSync, execSync, spawn, spawnSync };
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { execSync } from "node:child_process";
|
|
2
|
-
//#region src/services/childProcess/withHiddenWindow.ts
|
|
3
|
-
const withHiddenWindow = (parameters) => {
|
|
4
|
-
const optionsIndex = Array.isArray(parameters[0]) || parameters[0] === void 0 && parameters.length > 1 ? 1 : 0;
|
|
5
|
-
const options = parameters[optionsIndex];
|
|
6
|
-
if (typeof options === "object" && options !== null) return parameters.toSpliced(optionsIndex, 1, {
|
|
7
|
-
...options,
|
|
8
|
-
windowsHide: true
|
|
9
|
-
});
|
|
10
|
-
const isPlaceholder = options === void 0 && optionsIndex < parameters.length;
|
|
11
|
-
return parameters.toSpliced(optionsIndex, Number(isPlaceholder), { windowsHide: true });
|
|
12
|
-
};
|
|
13
|
-
//#endregion
|
|
14
|
-
//#region src/services/childProcess/execSync.ts
|
|
15
|
-
const execSync$1 = ((command, ...parameters) => execSync(command, ...withHiddenWindow(parameters)));
|
|
16
|
-
//#endregion
|
|
17
|
-
export { withHiddenWindow as n, execSync$1 as t };
|
package/dist/reporter.d.ts
DELETED
package/dist/reporter.js
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import "./bench.js";
|
|
2
|
-
import { t as execSync } from "./execSync-CtM99iYq.js";
|
|
3
|
-
import { GIBIBYTE, InvalidOperationError, Operation, getResult, getResultAsync, noop, normalizeString, takeOne } from "@esposter/shared";
|
|
4
|
-
import { arch, cpus, platform, release, totalmem } from "node:os";
|
|
5
|
-
import { writeFile } from "node:fs/promises";
|
|
6
|
-
//#region src/services/readBenchmarkEnvironment.ts
|
|
7
|
-
const readCommit = () => getResult(() => execSync("git rev-parse --short HEAD", {
|
|
8
|
-
encoding: "utf8",
|
|
9
|
-
stdio: "pipe"
|
|
10
|
-
})).match((stdout) => normalizeString(stdout), () => "unknown");
|
|
11
|
-
const readBenchmarkEnvironment = () => {
|
|
12
|
-
const cpu = cpus();
|
|
13
|
-
return [
|
|
14
|
-
`- Date: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
15
|
-
`- Commit: ${readCommit()}`,
|
|
16
|
-
`- Node: ${process.version}`,
|
|
17
|
-
`- OS: ${platform()} ${release()} (${arch()})`,
|
|
18
|
-
`- CPU: ${normalizeString(cpu[0]?.model) || "unknown"} × ${cpu.length}`,
|
|
19
|
-
`- RAM: ${(totalmem() / GIBIBYTE).toFixed(1)} GiB`
|
|
20
|
-
].join("\n");
|
|
21
|
-
};
|
|
22
|
-
//#endregion
|
|
23
|
-
//#region src/services/buildBenchmarkFileReport.ts
|
|
24
|
-
const getGroupName = (testCase, benchmarkName, benchmarkCount) => benchmarkCount > 1 ? `${testCase.fullName} > ${benchmarkName}` : testCase.fullName;
|
|
25
|
-
const buildBenchmarkFileReport = (filepath, testCases) => {
|
|
26
|
-
const groups = [];
|
|
27
|
-
for (const testCase of testCases) {
|
|
28
|
-
const testCaseBenchmarks = testCase.benchmarks();
|
|
29
|
-
for (const { name, tasks } of testCaseBenchmarks) {
|
|
30
|
-
const benchmarks = [];
|
|
31
|
-
for (const task of tasks.toSorted((firstTask, secondTask) => firstTask.rank - secondTask.rank)) {
|
|
32
|
-
if (!Number.isFinite(task.latency.mean)) throw new InvalidOperationError(Operation.Read, testCase.fullName, `benchmark "${task.name}" produced no samples — it likely threw on every iteration`);
|
|
33
|
-
benchmarks.push({
|
|
34
|
-
mean: task.latency.mean,
|
|
35
|
-
name: task.name,
|
|
36
|
-
p99: task.latency.p99,
|
|
37
|
-
rme: task.latency.rme,
|
|
38
|
-
sampleCount: task.latency.samplesCount
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
if (benchmarks.length > 0) groups.push({
|
|
42
|
-
benchmarks,
|
|
43
|
-
fullName: getGroupName(testCase, name, testCaseBenchmarks.length)
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return { files: [{
|
|
48
|
-
filepath,
|
|
49
|
-
groups
|
|
50
|
-
}] };
|
|
51
|
-
};
|
|
52
|
-
//#endregion
|
|
53
|
-
//#region src/services/formatBenchmarkMarkdown.ts
|
|
54
|
-
const getBaseline = (benchmarks) => benchmarks.find(({ name }) => name === "native") ?? benchmarks[0];
|
|
55
|
-
const formatRelative = (baselineMean, mean) => {
|
|
56
|
-
const ratio = baselineMean / mean;
|
|
57
|
-
return `${ratio >= 1 ? ratio.toFixed(2) : Number(ratio.toPrecision(2))}×`;
|
|
58
|
-
};
|
|
59
|
-
const HEADER = [
|
|
60
|
-
"task",
|
|
61
|
-
"vs base",
|
|
62
|
-
"mean (ms)",
|
|
63
|
-
"±rme",
|
|
64
|
-
"p99 (ms)",
|
|
65
|
-
"samples"
|
|
66
|
-
];
|
|
67
|
-
const formatTable = (rows) => {
|
|
68
|
-
const widths = rows.reduce((accumulator, row) => accumulator.map((width, index) => Math.max(width, takeOne(row, index).length)), HEADER.map((header) => header.length));
|
|
69
|
-
const formatRow = (cells) => `| ${cells.map((cell, index) => cell.padEnd(takeOne(widths, index))).join(" | ")} |`;
|
|
70
|
-
return [
|
|
71
|
-
formatRow(HEADER),
|
|
72
|
-
`| ${widths.map((width) => "-".repeat(width)).join(" | ")} |`,
|
|
73
|
-
...rows.map((row) => formatRow(row))
|
|
74
|
-
];
|
|
75
|
-
};
|
|
76
|
-
const formatBenchmarkMarkdown = (report, environment) => {
|
|
77
|
-
return [
|
|
78
|
-
"# Benchmark results",
|
|
79
|
-
"",
|
|
80
|
-
"Auto-generated by the BenchmarkMarkdownReporter on `pnpm bench`, colocated beside the bench file (a",
|
|
81
|
-
"`.bench.json` sits next to it). Diff over time to catch regressions. Tasks are listed fastest first.",
|
|
82
|
-
"`vs base` is a throughput multiplier against each group's baseline (the `native` task, else the",
|
|
83
|
-
"fastest): `1.00×` is the baseline, higher is faster, lower is slower — a fast task drifting back",
|
|
84
|
-
"toward `1.00×` is a regression. `±rme` is the relative margin of error.",
|
|
85
|
-
"Numbers are machine- and commit-dependent (see Environment); only compare runs from the same host.",
|
|
86
|
-
"",
|
|
87
|
-
"## Environment",
|
|
88
|
-
"",
|
|
89
|
-
environment,
|
|
90
|
-
"",
|
|
91
|
-
...report.files.flatMap((file) => file.groups.map((group) => {
|
|
92
|
-
const baselineMean = getBaseline(group.benchmarks)?.mean ?? NaN;
|
|
93
|
-
const rows = group.benchmarks.map(({ mean, name, p99, rme, sampleCount }) => [
|
|
94
|
-
name.replaceAll("|", String.raw`\|`),
|
|
95
|
-
formatRelative(baselineMean, mean),
|
|
96
|
-
mean.toFixed(4),
|
|
97
|
-
`±${rme.toFixed(2)}%`,
|
|
98
|
-
p99.toFixed(4),
|
|
99
|
-
`${sampleCount}`
|
|
100
|
-
]);
|
|
101
|
-
return [
|
|
102
|
-
`## ${group.fullName}`,
|
|
103
|
-
"",
|
|
104
|
-
...formatTable(rows),
|
|
105
|
-
""
|
|
106
|
-
].join("\n");
|
|
107
|
-
}))
|
|
108
|
-
].join("\n");
|
|
109
|
-
};
|
|
110
|
-
//#endregion
|
|
111
|
-
//#region src/services/writeBenchmarkReport.ts
|
|
112
|
-
const TS_EXTENSION_REGEX = /\.ts$/u;
|
|
113
|
-
const writeFileOrThrow = (path, contents) => getResultAsync(() => writeFile(path, contents)).match(noop, (error) => {
|
|
114
|
-
throw new InvalidOperationError(Operation.Create, path, error.message);
|
|
115
|
-
});
|
|
116
|
-
const writeBenchmarkReport = async (moduleId, relativeModuleId, testCases, environment) => {
|
|
117
|
-
const report = buildBenchmarkFileReport(relativeModuleId, testCases);
|
|
118
|
-
const [benchmarkFile] = report.files;
|
|
119
|
-
if (benchmarkFile === void 0 || benchmarkFile.groups.length === 0) return;
|
|
120
|
-
const basePath = moduleId.replace(TS_EXTENSION_REGEX, "");
|
|
121
|
-
const reportPath = basePath.endsWith(".platform.bench") ? `${basePath}.${process.platform}` : basePath;
|
|
122
|
-
await Promise.all([writeFileOrThrow(`${reportPath}.json`, `${JSON.stringify(report, null, 2)}\n`), writeFileOrThrow(`${reportPath}.md`, formatBenchmarkMarkdown(report, environment))]);
|
|
123
|
-
};
|
|
124
|
-
//#endregion
|
|
125
|
-
//#region src/services/BenchmarkMarkdownReporter.ts
|
|
126
|
-
var BenchmarkMarkdownReporter = class {
|
|
127
|
-
async onTestRunEnd(testModules) {
|
|
128
|
-
const environment = readBenchmarkEnvironment();
|
|
129
|
-
await Promise.all(testModules.map((testModule) => writeBenchmarkReport(testModule.moduleId, testModule.relativeModuleId, testModule.children.allTests(), environment)));
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
//#endregion
|
|
133
|
-
export { BenchmarkMarkdownReporter as default };
|