@elench/testkit 0.1.25 → 0.1.27

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.
@@ -1,190 +0,0 @@
1
- import crypto from "crypto";
2
- import fs from "fs";
3
- import path from "path";
4
- import { fileURLToPath } from "url";
5
-
6
- const TESTKIT_CONFIG = "testkit.config.json";
7
- const DEFAULT_RUNTIME_DIR = path.join("tests", "_testkit");
8
- const METADATA_FILE = ".runtime-manifest.json";
9
- const RUNTIME_FORMAT = 1;
10
-
11
- export function installRuntime(options = {}) {
12
- const productDir = resolveProductDir(process.cwd(), options.dir);
13
- const runtimeDir = resolveRuntimeDir(productDir, options.path);
14
- const sourceFiles = readBundledRuntimeFiles();
15
-
16
- fs.mkdirSync(runtimeDir, { recursive: true });
17
-
18
- for (const file of sourceFiles) {
19
- const targetPath = path.join(runtimeDir, file.path);
20
- fs.mkdirSync(path.dirname(targetPath), { recursive: true });
21
- fs.writeFileSync(targetPath, file.content);
22
- }
23
-
24
- const metadata = {
25
- format: RUNTIME_FORMAT,
26
- package: "@elench/testkit",
27
- version: readPackageVersion(),
28
- files: sourceFiles.map((file) => ({
29
- path: file.path,
30
- sha256: hashContent(file.content),
31
- })),
32
- };
33
- fs.writeFileSync(
34
- path.join(runtimeDir, METADATA_FILE),
35
- `${JSON.stringify(metadata, null, 2)}\n`
36
- );
37
-
38
- return {
39
- productDir,
40
- runtimeDir,
41
- relativeRuntimeDir: relativeToProduct(productDir, runtimeDir),
42
- files: metadata.files,
43
- };
44
- }
45
-
46
- export function getRuntimeStatus(options = {}) {
47
- const productDir = resolveProductDir(process.cwd(), options.dir);
48
- const runtimeDir = resolveRuntimeDir(productDir, options.path);
49
- const sourceFiles = readBundledRuntimeFiles();
50
- const metadataPath = path.join(runtimeDir, METADATA_FILE);
51
-
52
- if (!fs.existsSync(runtimeDir) || !fs.existsSync(metadataPath)) {
53
- return {
54
- status: "missing",
55
- productDir,
56
- runtimeDir,
57
- relativeRuntimeDir: relativeToProduct(productDir, runtimeDir),
58
- missingFiles: sourceFiles.map((file) => file.path),
59
- driftedFiles: [],
60
- };
61
- }
62
-
63
- const missingFiles = [];
64
- const driftedFiles = [];
65
-
66
- for (const file of sourceFiles) {
67
- const targetPath = path.join(runtimeDir, file.path);
68
- if (!fs.existsSync(targetPath)) {
69
- missingFiles.push(file.path);
70
- continue;
71
- }
72
-
73
- const installed = fs.readFileSync(targetPath, "utf8");
74
- if (installed !== file.content) {
75
- driftedFiles.push(file.path);
76
- }
77
- }
78
-
79
- const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf8"));
80
- const versionMatches = metadata.version === readPackageVersion();
81
-
82
- return {
83
- status:
84
- missingFiles.length === 0 && driftedFiles.length === 0 && versionMatches
85
- ? "installed"
86
- : "drifted",
87
- productDir,
88
- runtimeDir,
89
- relativeRuntimeDir: relativeToProduct(productDir, runtimeDir),
90
- versionMatches,
91
- missingFiles,
92
- driftedFiles,
93
- };
94
- }
95
-
96
- export function formatRuntimeStatus(result) {
97
- if (result.status === "missing") {
98
- return `Runtime not installed at ${result.relativeRuntimeDir}`;
99
- }
100
-
101
- if (result.status === "installed") {
102
- return `Runtime at ${result.relativeRuntimeDir} is up to date`;
103
- }
104
-
105
- const problems = [];
106
- if (result.missingFiles.length > 0) {
107
- problems.push(`missing: ${result.missingFiles.join(", ")}`);
108
- }
109
- if (result.driftedFiles.length > 0) {
110
- problems.push(`drifted: ${result.driftedFiles.join(", ")}`);
111
- }
112
- if (result.versionMatches === false) {
113
- problems.push("version drift");
114
- }
115
-
116
- return `Runtime at ${result.relativeRuntimeDir} is drifted (${problems.join("; ")})`;
117
- }
118
-
119
- function resolveProductDir(cwd, explicitDir) {
120
- const dir = explicitDir ? path.resolve(cwd, explicitDir) : cwd;
121
- ensureProductFiles(dir);
122
- return dir;
123
- }
124
-
125
- function ensureProductFiles(dir) {
126
- const missing = [TESTKIT_CONFIG].filter(
127
- (file) => !fs.existsSync(path.join(dir, file))
128
- );
129
-
130
- if (missing.length > 0) {
131
- throw new Error(
132
- `Expected ${missing.join(" and ")} in ${dir}. Either cd into a product directory or use --dir.`
133
- );
134
- }
135
- }
136
-
137
- function resolveRuntimeDir(productDir, explicitPath) {
138
- return path.resolve(productDir, explicitPath || DEFAULT_RUNTIME_DIR);
139
- }
140
-
141
- function relativeToProduct(productDir, targetPath) {
142
- return path.relative(productDir, targetPath) || ".";
143
- }
144
-
145
- function readBundledRuntimeFiles() {
146
- const sourceDir = path.resolve(
147
- path.dirname(fileURLToPath(import.meta.url)),
148
- "..",
149
- "runtime-src"
150
- );
151
-
152
- return walkRuntimeFiles(sourceDir);
153
- }
154
-
155
- function walkRuntimeFiles(rootDir, relativeDir = "") {
156
- const entries = fs.readdirSync(path.join(rootDir, relativeDir), {
157
- withFileTypes: true,
158
- });
159
- const files = [];
160
-
161
- for (const entry of entries) {
162
- const nextRelative = path.join(relativeDir, entry.name);
163
- if (entry.isDirectory()) {
164
- files.push(...walkRuntimeFiles(rootDir, nextRelative));
165
- continue;
166
- }
167
-
168
- const absolute = path.join(rootDir, nextRelative);
169
- files.push({
170
- path: nextRelative.split(path.sep).join("/"),
171
- content: fs.readFileSync(absolute, "utf8"),
172
- });
173
- }
174
-
175
- return files.sort((left, right) => left.path.localeCompare(right.path));
176
- }
177
-
178
- function readPackageVersion() {
179
- const packagePath = path.resolve(
180
- path.dirname(fileURLToPath(import.meta.url)),
181
- "..",
182
- "..",
183
- "package.json"
184
- );
185
- return JSON.parse(fs.readFileSync(packagePath, "utf8")).version;
186
- }
187
-
188
- function hashContent(content) {
189
- return crypto.createHash("sha256").update(content).digest("hex");
190
- }