@mesh-tech/mesh-cli
Version:
CLI for Mesh platform development utilities
74 lines (73 loc) • 2.42 kB
JavaScript
import { createHash } from "node:crypto";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { dirname, isAbsolute, join, relative } from "node:path";
export const WORKFLOW_PACKAGE_DIRS = [
"packages/agent-sdk/src",
"packages/workflow-interpreter/src",
"packages/agent-contracts/src",
];
const EXCLUDE = /(^|\/)(node_modules|dist|__tests__)(\/|$)|\.(test|spec)\.[cm]?tsx?$/;
export function findRepoRoot(startDir) {
let dir = startDir;
for (;;) {
if (existsSync(join(dir, "pnpm-workspace.yaml")))
return dir;
const parent = dirname(dir);
if (parent === dir)
return startDir;
dir = parent;
}
}
export function workflowSourceDirs(repoRoot, extraDirs = []) {
const pkgDirs = WORKFLOW_PACKAGE_DIRS.map((d) => join(repoRoot, d)).filter((d) => existsSync(d));
if (pkgDirs.length > 0)
return pkgDirs;
return extraDirs.filter((d) => existsSync(d));
}
export function resolveWorkerSourceDirs(repoRoot, services = {}) {
const dirs = [];
for (const [name, svc] of Object.entries(services)) {
if (/worker/i.test(name) && svc?.src) {
dirs.push(isAbsolute(svc.src) ? svc.src : join(repoRoot, svc.src));
}
}
return dirs;
}
export function computeWorkflowFingerprint(dirs, relativeTo) {
const files = [];
for (const dir of dirs) {
let rels;
try {
rels = readdirSync(dir, { recursive: true });
}
catch {
continue;
}
for (const rel of rels) {
const p = String(rel);
if (/\.(ts|tsx)$/.test(p) && !EXCLUDE.test(p))
files.push(join(dir, p));
}
}
files.sort();
if (files.length === 0)
return "";
const h = createHash("sha256");
for (const f of files) {
try {
const content = readFileSync(f);
h.update(relativeTo ? relative(relativeTo, f) : f);
h.update("\0");
h.update(content);
h.update("\0");
}
catch {
}
}
return h.digest("hex").slice(0, 16);
}
export function fingerprintWorkflowSource(appRoot, services = {}) {
const repoRoot = findRepoRoot(appRoot);
const workerDirs = resolveWorkerSourceDirs(repoRoot, services);
return computeWorkflowFingerprint(workflowSourceDirs(repoRoot, workerDirs), repoRoot);
}