refactor: generate bundled channel seams

This commit is contained in:
Peter Steinberger
2026-03-27 04:04:10 +00:00
parent 9a775aa59c
commit a10763e118
18 changed files with 290 additions and 107 deletions

View File

@@ -8,6 +8,22 @@ import { writeGeneratedOutput } from "./lib/generated-output-utils.mjs";
const GENERATED_BY = "scripts/generate-bundled-plugin-metadata.mjs";
const DEFAULT_OUTPUT_PATH = "src/plugins/bundled-plugin-metadata.generated.ts";
const DEFAULT_ENTRIES_OUTPUT_PATH = "src/generated/bundled-plugin-entries.generated.ts";
const DEFAULT_CHANNEL_ENTRIES_OUTPUT_PATH = "src/generated/bundled-channel-entries.generated.ts";
const DEFAULT_BUNDLED_CHANNEL_ENTRY_IDS = [
"bluebubbles",
"discord",
"feishu",
"imessage",
"irc",
"line",
"mattermost",
"nextcloud-talk",
"signal",
"slack",
"synology-chat",
"telegram",
"zalo",
];
const MANIFEST_KEY = "openclaw";
const FORMATTER_CWD = path.resolve(import.meta.dirname, "..");
@@ -295,6 +311,22 @@ function normalizeGeneratedImportPath(dirName, builtPath) {
return `../../extensions/${dirName}/${String(builtPath).replace(/^\.\//u, "")}`;
}
function resolveBundledChannelEntries(entries) {
const orderById = new Map(DEFAULT_BUNDLED_CHANNEL_ENTRY_IDS.map((id, index) => [id, index]));
return entries
.filter(
(entry) =>
Array.isArray(entry.manifest?.channels) &&
entry.manifest.channels.length > 0 &&
orderById.has(entry.manifest.id),
)
.toSorted(
(left, right) =>
(orderById.get(left.manifest.id) ?? Number.MAX_SAFE_INTEGER) -
(orderById.get(right.manifest.id) ?? Number.MAX_SAFE_INTEGER),
);
}
export async function collectBundledPluginMetadata(params = {}) {
const repoRoot = path.resolve(params.repoRoot ?? process.cwd());
const entries = [];
@@ -402,6 +434,38 @@ ${imports}
`;
}
export function renderBundledChannelEntriesModule(entries) {
const channelEntries = resolveBundledChannelEntries(entries);
const importLines = [];
const entryRecords = [];
for (const entry of channelEntries) {
const identifierBase = toIdentifier(entry.dirName).replace(/Plugin$/u, "");
const entryIdentifier = `${identifierBase}ChannelEntry`;
importLines.push(
`import ${entryIdentifier} from "${normalizeGeneratedImportPath(entry.dirName, entry.source.built)}";`,
);
let setupEntryIdentifier = null;
if (entry.setupSource?.built) {
setupEntryIdentifier = `${identifierBase}ChannelSetupEntry`;
importLines.push(
`import ${setupEntryIdentifier} from "${normalizeGeneratedImportPath(entry.dirName, entry.setupSource.built)}";`,
);
}
entryRecords.push(` {
id: ${JSON.stringify(entry.manifest.id)},
entry: ${entryIdentifier},
${setupEntryIdentifier ? ` setupEntry: ${setupEntryIdentifier},\n` : ""} }`);
}
return `// Auto-generated by ${GENERATED_BY}. Do not edit directly.
${importLines.join("\n")}
export const GENERATED_BUNDLED_CHANNEL_ENTRIES = [
${entryRecords.join(",\n")}
] as const;
`;
}
export async function writeBundledPluginMetadataModule(params = {}) {
const repoRoot = path.resolve(params.repoRoot ?? process.cwd());
const entries = await collectBundledPluginMetadata({ repoRoot });
@@ -410,12 +474,19 @@ export async function writeBundledPluginMetadataModule(params = {}) {
repoRoot,
params.entriesOutputPath ?? DEFAULT_ENTRIES_OUTPUT_PATH,
);
const channelEntriesOutputPath = path.resolve(
repoRoot,
params.channelEntriesOutputPath ?? DEFAULT_CHANNEL_ENTRIES_OUTPUT_PATH,
);
const metadataNext = formatTypeScriptModule(renderBundledPluginMetadataModule(entries), {
outputPath,
});
const registryNext = formatTypeScriptModule(renderBundledPluginEntriesModule(entries), {
outputPath: entriesOutputPath,
});
const channelEntriesNext = formatTypeScriptModule(renderBundledChannelEntriesModule(entries), {
outputPath: channelEntriesOutputPath,
});
const metadataResult = writeGeneratedOutput({
repoRoot,
outputPath: params.outputPath ?? DEFAULT_OUTPUT_PATH,
@@ -428,10 +499,20 @@ export async function writeBundledPluginMetadataModule(params = {}) {
next: registryNext,
check: params.check,
});
const channelEntriesResult = writeGeneratedOutput({
repoRoot,
outputPath: params.channelEntriesOutputPath ?? DEFAULT_CHANNEL_ENTRIES_OUTPUT_PATH,
next: channelEntriesNext,
check: params.check,
});
return {
changed: metadataResult.changed || entriesResult.changed,
wrote: metadataResult.wrote || entriesResult.wrote,
outputPaths: [metadataResult.outputPath, entriesResult.outputPath],
changed: metadataResult.changed || entriesResult.changed || channelEntriesResult.changed,
wrote: metadataResult.wrote || entriesResult.wrote || channelEntriesResult.wrote,
outputPaths: [
metadataResult.outputPath,
entriesResult.outputPath,
channelEntriesResult.outputPath,
],
};
}