Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | 17x 17x 17x 27x 27x 16x 16x 11x 11x 10x 1x 11x 11x 11x 11x 11x 14x 11x | import { dirname, join } from 'node:path';
import { existsSync, readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { createRequire } from 'node:module';
import { computeHash } from './cache.js';
import type { LoadedPlugin } from './plugin.js';
/**
* Walk up from `startPath` looking for the nearest `package.json` and return
* its `version`, or `''` if none is found within 10 levels, the file can't be
* parsed, or the field is missing. Best-effort — never throws.
*/
export function readNearestPackageVersion(startPath: string): string {
try {
let dir = dirname(startPath);
for (let i = 0; i < 10; i++) {
const candidate = join(dir, 'package.json');
if (existsSync(candidate)) {
const pkg = JSON.parse(readFileSync(candidate, 'utf-8')) as { version?: string };
return pkg.version ?? '';
}
const parent = dirname(dir);
if (parent === dir) return '';
dir = parent;
}
} catch {
// best-effort
}
return '';
}
/**
* Stable fingerprint of the codegen-affecting versions in play this run:
* `@contractkit/cli`, `@contractkit/core`, and every loaded plugin keyed by
* `name@version`. Used to invalidate the build cache when any of those
* packages is upgraded — otherwise stale generated TypeScript would persist
* until the next `--force` run.
*
* `cliEntryPath` should be the absolute path of the CLI entry module (the
* caller passes `fileURLToPath(import.meta.url)`); it's parameterized so the
* fingerprint is unit-testable without `import.meta` plumbing.
*/
export function computeCompilerFingerprint(plugins: LoadedPlugin[], cliEntryPath: string): string {
const cliVersion = readNearestPackageVersion(cliEntryPath);
let coreVersion = '';
try {
const corePkg = createRequire(cliEntryPath).resolve('@contractkit/core/package.json');
coreVersion = (JSON.parse(readFileSync(corePkg, 'utf-8')) as { version?: string }).version ?? '';
} catch {
// Optional — fingerprint just omits core when it can't be resolved.
}
const pluginParts = plugins.map(p => `${p.plugin.name}@${p.version}`).sort();
return computeHash(['cli', cliVersion, 'core', coreVersion, ...pluginParts].join('|'));
}
/** Convenience wrapper that derives the CLI entry path from the CLI's own `import.meta.url`. */
export function computeCompilerFingerprintFromImportMeta(plugins: LoadedPlugin[], importMetaUrl: string): string {
return computeCompilerFingerprint(plugins, fileURLToPath(importMetaUrl));
}
|