openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
154 lines (153 loc) • 5.42 kB
JavaScript
import { i as formatErrorMessage } from "./errors-BXgSefBE.js";
import { w as pathExists } from "./fs-safe-aqmM_n6V.js";
import { i as resolveSafeInstallDir, r as assertCanonicalPathWithinBase } from "./install-safe-path-C0w7ALW6.js";
import { a as isPrereleaseResolutionAllowed, n as formatPrereleaseResolutionError, s as parseRegistryNpmSpec } from "./npm-registry-spec-DjR-Lha9.js";
import { r as packNpmSpecToArchive, s as withTempDir } from "./install-source-utils-Zb798u54.js";
import { t as resolveNpmIntegrityDriftWithDefaultMessage } from "./npm-integrity-DwDjKpwi.js";
import fs from "node:fs/promises";
//#region src/infra/npm-pack-install.ts
/**
* Adapts installers with additional domain params to the shared npm-pack flow.
* The archive path stays owned by this module so callers cannot install a stale
* or caller-supplied tarball while reusing the npm resolution checks.
*/
async function installFromNpmSpecArchiveWithInstaller(params) {
return await installFromNpmSpecArchive({
tempDirPrefix: params.tempDirPrefix,
spec: params.spec,
timeoutMs: params.timeoutMs,
expectedIntegrity: params.expectedIntegrity,
onIntegrityDrift: params.onIntegrityDrift,
warn: params.warn,
installFromArchive: async ({ archivePath }) => await params.installFromArchive({
archivePath,
...params.archiveInstallParams
})
});
}
function isSuccessfulInstallResult(result) {
return result.ok;
}
/**
* Collapses the shared flow result back into the installer's result union while
* preserving npm metadata only for a successful install.
*/
function finalizeNpmSpecArchiveInstall(flowResult) {
if (!flowResult.ok) return flowResult;
const installResult = flowResult.installResult;
if (!isSuccessfulInstallResult(installResult)) return installResult;
return {
...installResult,
npmResolution: flowResult.npmResolution,
...flowResult.integrityDrift ? { integrityDrift: flowResult.integrityDrift } : {}
};
}
/**
* Packs a validated registry npm spec into a temporary tarball, verifies the
* resolved package metadata, then delegates archive extraction to the caller.
*/
async function installFromNpmSpecArchive(params) {
return await withTempDir(params.tempDirPrefix, async (tmpDir) => {
const parsedSpec = parseRegistryNpmSpec(params.spec);
if (!parsedSpec) return {
ok: false,
error: "unsupported npm spec"
};
const packedResult = await packNpmSpecToArchive({
spec: params.spec,
timeoutMs: params.timeoutMs,
cwd: tmpDir
});
if (!packedResult.ok) return packedResult;
const npmResolution = {
...packedResult.metadata,
resolvedAt: (/* @__PURE__ */ new Date()).toISOString()
};
if (npmResolution.version && !isPrereleaseResolutionAllowed({
spec: parsedSpec,
resolvedVersion: npmResolution.version
})) return {
ok: false,
error: formatPrereleaseResolutionError({
spec: parsedSpec,
resolvedVersion: npmResolution.version
})
};
const driftResult = await resolveNpmIntegrityDriftWithDefaultMessage({
spec: params.spec,
expectedIntegrity: params.expectedIntegrity,
resolution: npmResolution,
onIntegrityDrift: params.onIntegrityDrift,
warn: params.warn
});
if (driftResult.error) return {
ok: false,
error: driftResult.error
};
return {
ok: true,
installResult: await params.installFromArchive({ archivePath: packedResult.archivePath }),
npmResolution,
integrityDrift: driftResult.integrityDrift
};
});
}
//#endregion
//#region src/infra/install-mode-options.ts
/** Resolves shared install/update mode options with a required logger fallback. */
function resolveInstallModeOptions(params, defaultLogger) {
return {
logger: params.logger ?? defaultLogger,
mode: params.mode ?? "install",
dryRun: params.dryRun ?? false
};
}
/** Resolves install/update mode options plus an operation timeout default. */
function resolveTimedInstallModeOptions(params, defaultLogger, defaultTimeoutMs = 12e4) {
return {
...resolveInstallModeOptions(params, defaultLogger),
timeoutMs: params.timeoutMs ?? defaultTimeoutMs
};
}
//#endregion
//#region src/infra/install-target.ts
/** Resolves and verifies an install target directory under a canonical base directory. */
async function resolveCanonicalInstallTarget(params) {
await fs.mkdir(params.baseDir, { recursive: true });
const targetDirResult = resolveSafeInstallDir({
baseDir: params.baseDir,
id: params.id,
invalidNameMessage: params.invalidNameMessage,
nameEncoder: params.nameEncoder
});
if (!targetDirResult.ok) return {
ok: false,
error: targetDirResult.error
};
try {
await assertCanonicalPathWithinBase({
baseDir: params.baseDir,
candidatePath: targetDirResult.path,
boundaryLabel: params.boundaryLabel
});
} catch (err) {
return {
ok: false,
error: formatErrorMessage(err)
};
}
return {
ok: true,
targetDir: targetDirResult.path
};
}
/** Ensures install mode does not overwrite an existing target; update mode may reuse it. */
async function ensureInstallTargetAvailable(params) {
if (params.mode === "install" && await pathExists(params.targetDir)) return {
ok: false,
error: params.alreadyExistsError
};
return { ok: true };
}
//#endregion
export { finalizeNpmSpecArchiveInstall as a, resolveTimedInstallModeOptions as i, resolveCanonicalInstallTarget as n, installFromNpmSpecArchiveWithInstaller as o, resolveInstallModeOptions as r, ensureInstallTargetAvailable as t };