UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

154 lines (153 loc) 5.42 kB
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 };