Files
openclaw/scripts/write-plugin-sdk-entry-dts.ts
Dallin Romney 3005b62242 perf(plugins) refactor plugin SDK declarations for flat package types (#87165)
* refactor: flatten plugin sdk declarations

* fix: align package inventory with flat sdk declarations

* refactor: move packed sdk smoke to fixture

* test: simplify packed sdk type smoke

* fix(canvas): use focused number runtime helpers

* fix(ci): stabilize sdk boundary checks

* test: guard private sdk declaration leaks

Co-authored-by: Peter Steinberger <steipete@gmail.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-27 19:22:32 -07:00

122 lines
4.1 KiB
TypeScript

import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { build } from "tsdown";
import { buildPluginSdkEntrySources, pluginSdkEntrypoints } from "./lib/plugin-sdk-entries.mjs";
const RUNTIME_SHIMS: Partial<Record<string, string>> = {
"webhook-path": [
"/** Normalize webhook paths into the canonical registry form used by route lookup. */",
"export function normalizeWebhookPath(raw) {",
" const trimmed = raw.trim();",
" if (!trimmed) {",
' return "/";',
" }",
' const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;',
' if (withSlash.length > 1 && withSlash.endsWith("/")) {',
" return withSlash.slice(0, -1);",
" }",
" return withSlash;",
"}",
"",
"/** Resolve the effective webhook path from explicit path, URL, or default fallback. */",
"export function resolveWebhookPath(params) {",
" const trimmedPath = params.webhookPath?.trim();",
" if (trimmedPath) {",
" return normalizeWebhookPath(trimmedPath);",
" }",
" if (params.webhookUrl?.trim()) {",
" try {",
" const parsed = new URL(params.webhookUrl);",
' return normalizeWebhookPath(parsed.pathname || "/");',
" } catch {",
" return null;",
" }",
" }",
" return params.defaultPath ?? null;",
"}",
"",
].join("\n"),
};
function isBareImportSpecifier(id: string): boolean {
return !id.startsWith(".") && !id.startsWith("/") && !/^[A-Za-z]:[\\/]/u.test(id);
}
function removeExistingFlatDeclarations(outDir: string): void {
if (!fs.existsSync(outDir)) {
return;
}
for (const entry of fs.readdirSync(outDir, { withFileTypes: true })) {
if (!entry.isFile() || !entry.name.endsWith(".d.ts")) {
continue;
}
fs.rmSync(path.join(outDir, entry.name), { force: true });
}
}
function copyFlatDeclarations(fromDir: string, toDir: string): void {
fs.mkdirSync(toDir, { recursive: true });
for (const entry of fs.readdirSync(fromDir, { withFileTypes: true })) {
if (!entry.isFile() || !entry.name.endsWith(".d.ts")) {
continue;
}
fs.copyFileSync(path.join(fromDir, entry.name), path.join(toDir, entry.name));
}
}
const distPluginSdkDir = path.join(process.cwd(), "dist/plugin-sdk");
const flatDeclarationTempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-plugin-sdk-dts-"));
try {
await build({
clean: true,
config: false,
deps: { neverBundle: (id) => isBareImportSpecifier(id) },
dts: true,
entry: buildPluginSdkEntrySources(),
failOnWarn: false,
fixedExtension: false,
format: "esm",
logLevel: "error",
outDir: flatDeclarationTempDir,
outExtensions: () => ({ js: ".js", dts: ".d.ts" }),
platform: "node",
report: false,
tsconfig: "tsconfig.plugin-sdk.dts.json",
});
removeExistingFlatDeclarations(distPluginSdkDir);
copyFlatDeclarations(flatDeclarationTempDir, distPluginSdkDir);
} finally {
fs.rmSync(flatDeclarationTempDir, { recursive: true, force: true });
}
// The root npm package ships flat bundled declarations under `dist/plugin-sdk`.
// The private workspace package keeps source-shaped declaration paths for local
// package-boundary projects, so bridge them back to the packaged flat entries.
for (const entry of pluginSdkEntrypoints) {
const packageTypeOut = path.join(
process.cwd(),
`packages/plugin-sdk/dist/src/plugin-sdk/${entry}.d.ts`,
);
fs.mkdirSync(path.dirname(packageTypeOut), { recursive: true });
fs.writeFileSync(
packageTypeOut,
`export * from "../../../../../dist/plugin-sdk/${entry}.js";\n`,
"utf8",
);
const runtimeShim = RUNTIME_SHIMS[entry];
if (!runtimeShim) {
continue;
}
const runtimeOut = path.join(process.cwd(), `dist/plugin-sdk/${entry}.js`);
fs.mkdirSync(path.dirname(runtimeOut), { recursive: true });
fs.writeFileSync(runtimeOut, runtimeShim, "utf8");
}
const stampPath = path.join(process.cwd(), "dist/plugin-sdk/.boundary-entry-shims.stamp");
fs.mkdirSync(path.dirname(stampPath), { recursive: true });
fs.writeFileSync(stampPath, `${new Date().toISOString()}\n`, "utf8");