Files
pikasTech-HWLAB/scripts/src/dev-artifact-services.mjs
T
2026-05-30 12:31:07 +08:00

158 lines
4.7 KiB
JavaScript

import { constants as fsConstants } from "node:fs";
import { access } from "node:fs/promises";
import path from "node:path";
export const BUILDABLE_IMPLEMENTATION_STATES = Object.freeze([
"repo-entrypoint",
"static-web-wrapper",
"repo-bundle"
]);
const buildableImplementationStates = new Set(BUILDABLE_IMPLEMENTATION_STATES);
async function pathExists(repoRoot, relativePath) {
try {
await access(path.join(repoRoot, relativePath), fsConstants.R_OK);
return true;
} catch {
return false;
}
}
export function publishEnabledForService(service) {
return service.sourceState !== "intentionally-disabled" &&
buildableImplementationStates.has(service.implementationState);
}
export function notPublishedReasonForService(service) {
if (publishEnabledForService(service)) {
return "publish_not_run";
}
if (service.sourceState === "intentionally-disabled") {
return "disabled_intentionally";
}
if (service.implementationState === "missing-runtime-entrypoint") {
return "disabled_missing_runtime_entrypoint";
}
if (service.implementationState === "library-only") {
return "disabled_missing_executable_entrypoint";
}
return `disabled_${service.implementationState}`;
}
export function servicePublishPolicy(service) {
const publishEnabled = publishEnabledForService(service);
return {
publishEnabled,
artifactRequired: publishEnabled,
artifactScope: publishEnabled ? "required" : "disabled",
notPublishedReason: publishEnabled ? "publish_not_run" : notPublishedReasonForService(service)
};
}
export function withServicePublishPolicy(service) {
return {
...service,
...servicePublishPolicy(service)
};
}
function serviceSourceState(catalog, serviceId) {
return catalog?.services?.find((service) => service.serviceId === serviceId)?.sourceState ?? "source-present";
}
export async function resolveDevArtifactService(repoRoot, serviceId, catalog = null) {
const sourceState = serviceSourceState(catalog, serviceId);
const tsCmdPath = `cmd/${serviceId}/main.ts`;
if (await pathExists(repoRoot, tsCmdPath)) {
return withServicePublishPolicy({
serviceId,
runtimeKind: "bun-command",
entrypoint: tsCmdPath,
implementationState: "repo-entrypoint",
sourceState
});
}
const cmdPath = `cmd/${serviceId}/main.mjs`;
if (await pathExists(repoRoot, cmdPath)) {
return withServicePublishPolicy({
serviceId,
runtimeKind: "node-command",
entrypoint: cmdPath,
implementationState: "repo-entrypoint",
sourceState
});
}
if (serviceId === "hwlab-cloud-web") {
return withServicePublishPolicy({
serviceId,
runtimeKind: "cloud-web",
entrypoint: "web/hwlab-cloud-web/index.html",
implementationState: "static-web-wrapper",
sourceState
});
}
if (serviceId === "hwlab-agent-skills") {
return withServicePublishPolicy({
serviceId,
runtimeKind: "skills-bundle",
entrypoint: "skills/hwlab-agent-runtime/SKILL.md",
implementationState: "repo-bundle",
sourceState
});
}
return withServicePublishPolicy({
serviceId,
runtimeKind: "health-placeholder",
entrypoint: null,
implementationState: "missing-runtime-entrypoint",
sourceState
});
}
export async function resolveDevArtifactServices(repoRoot, serviceIds, frozenServiceIds, catalog = null) {
const unknown = serviceIds.filter((serviceId) => !frozenServiceIds.includes(serviceId));
if (unknown.length > 0) {
throw new Error(`unknown service IDs: ${unknown.join(", ")}`);
}
const services = [];
for (const serviceId of serviceIds) {
services.push(await resolveDevArtifactService(repoRoot, serviceId, catalog));
}
return services;
}
export function serviceInventoryFromServices(services) {
const requiredServiceIds = services
.filter((service) => service.artifactRequired)
.map((service) => service.serviceId);
const disabledServiceIds = services
.filter((service) => !service.artifactRequired)
.map((service) => service.serviceId);
return {
version: "v2",
serviceCount: services.length,
requiredServiceCount: requiredServiceIds.length,
disabledServiceCount: disabledServiceIds.length,
requiredServiceIds,
disabledServiceIds,
services: services.map((service) => ({
serviceId: service.serviceId,
publishEnabled: service.publishEnabled,
artifactRequired: service.artifactRequired,
artifactScope: service.artifactScope,
runtimeKind: service.runtimeKind,
implementationState: service.implementationState,
sourceState: service.sourceState,
entrypoint: service.entrypoint,
disabledReason: service.artifactRequired ? null : service.notPublishedReason
}))
};
}