if (pkg.name !== "openclaw") {
errors.push(`package.json name must be "openclaw"; found "${pkg.name ?? ""}".`);
} if (!pkg.description?.trim()) {
errors.push("package.json description must be non-empty.");
} if (pkg.license !== "MIT") {
errors.push(`package.json license must be "MIT"; found "${pkg.license ?? ""}".`);
} if (actualRepositoryUrl !== EXPECTED_REPOSITORY_URL) {
errors.push(
`package.json repository.url must resolve to ${EXPECTED_REPOSITORY_URL}; found ${
actualRepositoryUrl || "<missing>"
}.`,
);
} if (pkg.bin?.openclaw !== "openclaw.mjs") {
errors.push(
`package.json bin.openclaw must be "openclaw.mjs"; found "${pkg.bin?.openclaw ?? ""}".`,
);
} if (pkg.dependencies?.[OPTIONAL_LOCAL_EMBEDDING_RUNTIME_PACKAGE]) {
errors.push(
`package.json dependencies["${OPTIONAL_LOCAL_EMBEDDING_RUNTIME_PACKAGE}"] must be omitted; keep it optional.`,
);
} if (pkg.optionalDependencies?.[OPTIONAL_LOCAL_EMBEDDING_RUNTIME_PACKAGE]) {
errors.push(
`package.json optionalDependencies["${OPTIONAL_LOCAL_EMBEDDING_RUNTIME_PACKAGE}"] must be omitted; keep it operator-installed.`,
);
} if (pkg.peerDependencies?.[OPTIONAL_LOCAL_EMBEDDING_RUNTIME_PACKAGE]) {
errors.push(
`package.json peerDependencies["${OPTIONAL_LOCAL_EMBEDDING_RUNTIME_PACKAGE}"] must be omitted; keep it optional.`,
);
} if (pkg.peerDependenciesMeta?.[OPTIONAL_LOCAL_EMBEDDING_RUNTIME_PACKAGE]) {
errors.push(
`package.json peerDependenciesMeta["${OPTIONAL_LOCAL_EMBEDDING_RUNTIME_PACKAGE}"] must be omitted; keep it optional.`,
);
}
const parsedVersion = parseReleaseVersion(packageVersion); if (parsedVersion === null) {
errors.push(
`package.json version must match YYYY.M.D, YYYY.M.D-N, or YYYY.M.D-beta.N; found "${packageVersion || "<missing>"}".`,
);
}
if (!releaseTag.startsWith("v")) {
errors.push(`Release tag must start with "v"; found "${releaseTag || "<missing>"}".`);
}
const tagVersion = releaseTag.startsWith("v") ? releaseTag.slice(1) : releaseTag; const parsedTag = parseReleaseTagVersion(tagVersion); if (parsedTag === null) {
errors.push(
`Release tag must match vYYYY.M.D, vYYYY.M.D-beta.N, or fallback correction tag vYYYY.M.D-N; found "${releaseTag || "<missing>"}".`,
);
}
if (parsedVersion !== null) { const dayDistance = utcCalendarDayDistance(parsedVersion.date, now); if (dayDistance > MAX_CALVER_DISTANCE_DAYS) { const nowLabel = now.toISOString().slice(0, 10); const versionDate = parsedVersion.date.toISOString().slice(0, 10);
errors.push(
`Release version ${packageVersion} is ${dayDistance} days away from current UTC date ${nowLabel}; release CalVer date ${versionDate} must be within ${MAX_CALVER_DISTANCE_DAYS} days.`,
);
}
}
if (params.releaseSha?.trim() && params.releaseMainRef?.trim()) { try {
execFileSync( "git",
["merge-base", "--is-ancestor", params.releaseSha, params.releaseMainRef],
{ stdio: "ignore" },
);
} catch {
errors.push(
`Tagged commit ${params.releaseSha} is not contained in ${params.releaseMainRef}.`,
);
}
}
return errors;
}
function loadPackageJson(): PackageJson { return JSON.parse(readFileSync("package.json", "utf8")) as PackageJson;
}
function isNpmExecPath(value: string): boolean { return /^npm(?:-cli)?(?:\.(?:c?js|cmd|exe))?$/.test(basename(value).toLowerCase());
}
for (const candidate of candidates) { try { const parsed = JSON.parse(candidate) as unknown; if (Array.isArray(parsed)) { return parsed as NpmPackResult[];
}
} catch { // Try the next candidate. npm lifecycle output can prepend non-JSON logs.
}
}
for (const requiredPath of REQUIRED_PACKED_PATHS) { if (!packedPaths.has(requiredPath)) {
errors.push(
`npm package is missing required path "${requiredPath}". Ensure UI assets are built and included before publish.`,
);
}
}
if (assetPaths.length === 0) {
errors.push(
`npm package is missing Control UI asset payload under "${CONTROL_UI_ASSET_PREFIX}". Refuse release when the dashboard tarball would be empty.`,
);
}
export function collectForbiddenPackedPathErrors(paths: Iterable<string>): string[] { const errors: string[] = []; for (const packedPath of paths) { const matchedRule = FORBIDDEN_PACKED_PATH_RULES.find((rule) =>
packedPath.startsWith(rule.prefix),
); if (!matchedRule) { continue;
}
errors.push(matchedRule.describe(packedPath));
} return errors.toSorted((left, right) => left.localeCompare(right));
}
export function collectForbiddenPackedContentErrors(
paths: Iterable<string>,
rootDir = process.cwd(),
): string[] { const textPathPattern = /\.(?:[cm]?js|d\.ts|json|md|mjs|cjs)$/u; const errors: string[] = []; for (const packedPath of paths) { if (packedPath === PACKAGE_DIST_INVENTORY_RELATIVE_PATH) { continue;
} if (
!FORBIDDEN_PRIVATE_QA_CONTENT_SCAN_PREFIXES.some((prefix) => packedPath.startsWith(prefix))
) { continue;
} if (!textPathPattern.test(packedPath)) { continue;
}
let content: string; try {
content = readFileSync(pathToFileURL(join(rootDir, packedPath)), "utf8");
} catch { continue;
} const matchedMarker = FORBIDDEN_PRIVATE_QA_CONTENT_MARKERS.find((marker) =>
content.includes(marker),
); if (!matchedMarker) { continue;
}
errors.push(
`npm package must not include private QA lab marker "${matchedMarker}" in "${packedPath}".`,
);
} return errors.toSorted((left, right) => left.localeCompare(right));
}
export function collectPackedTestCargoErrors(paths: Iterable<string>): string[] { const errors: string[] = []; for (const packedPath of paths) { if (!pathContainsPackedTestCargo(packedPath)) { continue;
}
errors.push(`npm package must not include test cargo "${packedPath}".`);
} return errors.toSorted((left, right) => left.localeCompare(right));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.