UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

97 lines (84 loc) 2.98 kB
// Scans packaged dist JavaScript for relative imports and missing closure entries. import { createRequire } from "node:module"; import path from "node:path"; import { visitModuleSpecifiers } from "./guard-inventory-utils.mjs"; const require = createRequire(import.meta.url); const ts = require("typescript"); const JS_DIST_FILE_RE = /^dist\/.*\.(?:cjs|js|mjs)$/u; function normalizePackagePath(value) { return value.replace(/\\/gu, "/").replace(/^package\//u, ""); } function stripSpecifierSuffix(value) { return value.replace(/[?#].*$/u, ""); } function hasJavaScriptFileExtension(value) { return /\.(?:cjs|js|mjs)$/u.test(path.posix.basename(stripSpecifierSuffix(value))); } function resolveDistImportPath(importerPath, specifier) { if (!specifier.startsWith(".")) { return null; } const stripped = stripSpecifierSuffix(specifier); if (!stripped) { return null; } return path.posix.normalize(path.posix.join(path.posix.dirname(importerPath), stripped)); } function collectImportSpecifiers(source, importerPath) { const specifiers = []; const sourceFile = ts.createSourceFile( importerPath, source, ts.ScriptTarget.Latest, false, ts.ScriptKind.JS, ); visitModuleSpecifiers( ts, sourceFile, ({ kind, specifier }) => { if ( specifier.startsWith(".") && (kind !== "import-meta-url" || (hasJavaScriptFileExtension(specifier) && resolveDistImportPath(importerPath, specifier)?.startsWith("dist/"))) ) { specifiers.push(specifier); } }, { includeCommonJs: true, includeImportMetaUrl: true }, ); return specifiers; } /** Collect missing-file errors for relative imports inside package dist files. */ export function collectPackageDistImportErrors(params) { const files = [...new Set(params.files.map(normalizePackagePath))]; const fileSet = new Set(files); const errors = []; const imports = params.imports ?? collectPackageDistImports({ files, readText: params.readText }); for (const { importerPath, importedPath } of imports) { if (!fileSet.has(importedPath)) { errors.push(`${importerPath} imports missing ${importedPath}`); } } return errors; } /** Collect relative dist import edges from package JavaScript files. */ function collectPackageDistImports(params) { const files = [...new Set(params.files.map(normalizePackagePath))]; const imports = []; for (const importerPath of files.toSorted((left, right) => left.localeCompare(right))) { if (!JS_DIST_FILE_RE.test(importerPath) || importerPath.includes("/node_modules/")) { continue; } const source = params.readText(importerPath); for (const specifier of collectImportSpecifiers(source, importerPath)) { const importedPath = resolveDistImportPath(importerPath, specifier); if (!importedPath) { continue; } imports.push({ importerPath, importedPath }); } } return imports; }