mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 00:40:22 +00:00
refactor(core): dedupe command, hook, and cron fixtures
This commit is contained in:
@@ -3,11 +3,15 @@ import path from "node:path";
|
||||
import { MANIFEST_KEY } from "../compat/legacy-names.js";
|
||||
import { fileExists, readJsonFile, resolveArchiveKind } from "../infra/archive.js";
|
||||
import { resolveExistingInstallPath, withExtractedArchiveRoot } from "../infra/install-flow.js";
|
||||
import { installFromValidatedNpmSpecArchive } from "../infra/install-from-npm-spec.js";
|
||||
import {
|
||||
resolveInstallModeOptions,
|
||||
resolveTimedInstallModeOptions,
|
||||
} from "../infra/install-mode-options.js";
|
||||
import { installPackageDir } from "../infra/install-package-dir.js";
|
||||
import {
|
||||
installPackageDir,
|
||||
installPackageDirWithManifestDeps,
|
||||
} from "../infra/install-package-dir.js";
|
||||
import { resolveSafeInstallDir, unscopedPackageName } from "../infra/install-safe-path.js";
|
||||
import {
|
||||
type NpmIntegrityDrift,
|
||||
@@ -18,11 +22,6 @@ import {
|
||||
ensureInstallTargetAvailable,
|
||||
resolveCanonicalInstallTarget,
|
||||
} from "../infra/install-target.js";
|
||||
import {
|
||||
finalizeNpmSpecArchiveInstall,
|
||||
installFromNpmSpecArchiveWithInstaller,
|
||||
} from "../infra/npm-pack-install.js";
|
||||
import { validateRegistryNpmSpec } from "../infra/npm-registry-spec.js";
|
||||
import { isPathInside, isPathInsideWithRealpath } from "../security/scan-paths.js";
|
||||
import { CONFIG_DIR, resolveUserPath } from "../utils.js";
|
||||
import { parseFrontmatter } from "./frontmatter.js";
|
||||
@@ -231,17 +230,15 @@ async function installHookPackageFromDir(params: {
|
||||
};
|
||||
}
|
||||
|
||||
const deps = manifest.dependencies ?? {};
|
||||
const hasDeps = Object.keys(deps).length > 0;
|
||||
const installRes = await installPackageDir({
|
||||
const installRes = await installPackageDirWithManifestDeps({
|
||||
sourceDir: params.packageDir,
|
||||
targetDir,
|
||||
mode,
|
||||
timeoutMs,
|
||||
logger,
|
||||
copyErrorPrefix: "failed to copy hook pack",
|
||||
hasDeps,
|
||||
depsLogMessage: "Installing hook pack dependencies…",
|
||||
manifestDependencies: manifest.dependencies,
|
||||
});
|
||||
if (!installRes.ok) {
|
||||
return installRes;
|
||||
@@ -376,14 +373,10 @@ export async function installHooksFromNpmSpec(params: {
|
||||
}): Promise<InstallHooksResult> {
|
||||
const { logger, timeoutMs, mode, dryRun } = resolveTimedInstallModeOptions(params, defaultLogger);
|
||||
const expectedHookPackId = params.expectedHookPackId;
|
||||
const spec = params.spec.trim();
|
||||
const specError = validateRegistryNpmSpec(spec);
|
||||
if (specError) {
|
||||
return { ok: false, error: specError };
|
||||
}
|
||||
const spec = params.spec;
|
||||
|
||||
logger.info?.(`Downloading ${spec}…`);
|
||||
const flowResult = await installFromNpmSpecArchiveWithInstaller({
|
||||
logger.info?.(`Downloading ${spec.trim()}…`);
|
||||
return await installFromValidatedNpmSpecArchive({
|
||||
tempDirPrefix: "openclaw-hook-pack-",
|
||||
spec,
|
||||
timeoutMs,
|
||||
@@ -402,7 +395,6 @@ export async function installHooksFromNpmSpec(params: {
|
||||
expectedHookPackId,
|
||||
},
|
||||
});
|
||||
return finalizeNpmSpecArchiveInstall(flowResult);
|
||||
}
|
||||
|
||||
export async function installHooksFromPath(params: {
|
||||
|
||||
@@ -5,6 +5,22 @@ import { describe, expect, it } from "vitest";
|
||||
import { MANIFEST_KEY } from "../compat/legacy-names.js";
|
||||
import { loadHookEntriesFromDir } from "./workspace.js";
|
||||
|
||||
function writeHookPackageManifest(pkgDir: string, hooks: string[]): void {
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "package.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
name: "pkg",
|
||||
[MANIFEST_KEY]: {
|
||||
hooks,
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
describe("hooks workspace", () => {
|
||||
it("ignores package.json hook paths that traverse outside package directory", () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-hooks-workspace-"));
|
||||
@@ -19,19 +35,7 @@ describe("hooks workspace", () => {
|
||||
fs.writeFileSync(path.join(outsideHookDir, "HOOK.md"), "---\nname: outside\n---\n");
|
||||
fs.writeFileSync(path.join(outsideHookDir, "handler.js"), "export default async () => {};\n");
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "package.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
name: "pkg",
|
||||
[MANIFEST_KEY]: {
|
||||
hooks: ["../outside"],
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
writeHookPackageManifest(pkgDir, ["../outside"]);
|
||||
|
||||
const entries = loadHookEntriesFromDir({ dir: hooksRoot, source: "openclaw-workspace" });
|
||||
expect(entries.some((e) => e.hook.name === "outside")).toBe(false);
|
||||
@@ -49,19 +53,7 @@ describe("hooks workspace", () => {
|
||||
fs.writeFileSync(path.join(nested, "HOOK.md"), "---\nname: nested\n---\n");
|
||||
fs.writeFileSync(path.join(nested, "handler.js"), "export default async () => {};\n");
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "package.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
name: "pkg",
|
||||
[MANIFEST_KEY]: {
|
||||
hooks: ["./nested"],
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
writeHookPackageManifest(pkgDir, ["./nested"]);
|
||||
|
||||
const entries = loadHookEntriesFromDir({ dir: hooksRoot, source: "openclaw-workspace" });
|
||||
expect(entries.some((e) => e.hook.name === "nested")).toBe(true);
|
||||
@@ -85,19 +77,7 @@ describe("hooks workspace", () => {
|
||||
return;
|
||||
}
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "package.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
name: "pkg",
|
||||
[MANIFEST_KEY]: {
|
||||
hooks: ["./linked"],
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
writeHookPackageManifest(pkgDir, ["./linked"]);
|
||||
|
||||
const entries = loadHookEntriesFromDir({ dir: hooksRoot, source: "openclaw-workspace" });
|
||||
expect(entries.some((e) => e.hook.name === "outside")).toBe(false);
|
||||
|
||||
Reference in New Issue
Block a user