




















@@ -4,12 +4,14 @@ import { fileURLToPath } from "node:url";
44import { describe, expect, it } from "vitest";
55import {
66pluginSdkEntrypoints,
7+publicPluginOwnedSdkEntrypoints,
78reservedBundledPluginSdkEntrypoints,
89supportedBundledFacadeSdkEntrypoints,
910} from "../../plugin-sdk/entrypoints.js";
10111112const ROOT_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
1213const REPO_ROOT = resolve(ROOT_DIR, "..");
14+const SDK_SUBPATH_DOC_FILE = "docs/plugins/sdk-subpaths.md";
1315const PUBLIC_CONTRACT_REFERENCE_FILES = [
1416"docs/plugins/architecture.md",
1517"src/plugins/contracts/plugin-sdk-subpaths.test.ts",
@@ -57,6 +59,48 @@ function collectPluginSdkSubpathReferences() {
5759return references;
5860}
596162+function collectDocumentedSdkSubpaths(): Set<string> {
63+const source = readFileSync(resolve(REPO_ROOT, SDK_SUBPATH_DOC_FILE), "utf8");
64+return new Set(
65+[...source.matchAll(/`plugin-sdk\/([a-z0-9][a-z0-9-]*)`/g)]
66+.map((match) => match[1])
67+.filter((subpath): subpath is string => Boolean(subpath)),
68+);
69+}
70+71+function collectBundledPluginIds(): string[] {
72+return readdirSync(resolve(REPO_ROOT, "extensions"), { withFileTypes: true })
73+.filter((entry) => entry.isDirectory())
74+.map((entry) => entry.name)
75+.toSorted((a, b) => b.length - a.length || a.localeCompare(b));
76+}
77+78+function collectPluginOwnedSdkEntrypoints(): string[] {
79+const pluginIds = collectBundledPluginIds();
80+return pluginSdkEntrypoints
81+.filter((entrypoint) =>
82+pluginIds.some(
83+(pluginId) => entrypoint === pluginId || entrypoint.startsWith(`${pluginId}-`),
84+),
85+)
86+.toSorted();
87+}
88+89+function collectClassificationOverlaps(classifications: Record<string, readonly string[]>) {
90+const seen = new Map<string, string[]>();
91+for (const [classification, entrypoints] of Object.entries(classifications)) {
92+for (const entrypoint of entrypoints) {
93+const current = seen.get(entrypoint) ?? [];
94+current.push(classification);
95+seen.set(entrypoint, current);
96+}
97+}
98+return [...seen.entries()]
99+.filter(([, matches]) => matches.length > 1)
100+.map(([entrypoint, matches]) => `${entrypoint}: ${matches.toSorted().join(", ")}`)
101+.toSorted();
102+}
103+60104function collectBundledFacadeSdkEntrypoints(): string[] {
61105const entrypoints: string[] = [];
62106for (const entrypoint of pluginSdkEntrypoints) {
@@ -224,6 +268,43 @@ describe("plugin-sdk package contract guardrails", () => {
224268});
225269});
226270271+it("keeps plugin-owned SDK subpaths explicitly classified and documented", () => {
272+const entrypoints = new Set(pluginSdkEntrypoints);
273+const reserved = new Set<string>(reservedBundledPluginSdkEntrypoints);
274+const supported = new Set<string>(supportedBundledFacadeSdkEntrypoints);
275+const publicOwned = new Set<string>(publicPluginOwnedSdkEntrypoints);
276+const documented = collectDocumentedSdkSubpaths();
277+const pluginOwnedEntrypoints = collectPluginOwnedSdkEntrypoints();
278+const classified = new Set([...reserved, ...supported, ...publicOwned]);
279+280+const unknownPublicOwned = [...publicOwned].filter(
281+(entrypoint) => !entrypoints.has(entrypoint),
282+);
283+const classificationOverlaps = collectClassificationOverlaps({
284+reserved: reservedBundledPluginSdkEntrypoints,
285+supported: supportedBundledFacadeSdkEntrypoints,
286+publicOwned: publicPluginOwnedSdkEntrypoints,
287+});
288+const unclassifiedPluginOwned = pluginOwnedEntrypoints.filter(
289+(entrypoint) => !classified.has(entrypoint),
290+);
291+const undocumentedPluginOwned = pluginOwnedEntrypoints.filter(
292+(entrypoint) => !documented.has(entrypoint),
293+);
294+295+expect({
296+ unknownPublicOwned,
297+ classificationOverlaps,
298+ unclassifiedPluginOwned,
299+ undocumentedPluginOwned,
300+}).toEqual({
301+unknownPublicOwned: [],
302+classificationOverlaps: [],
303+unclassifiedPluginOwned: [],
304+undocumentedPluginOwned: [],
305+});
306+});
307+227308it("keeps curated public plugin-sdk references on exported built subpaths", () => {
228309const entrypoints = new Set(pluginSdkEntrypoints);
229310const exports = new Set(collectPluginSdkPackageExports());
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。