fix(plugins): isole les menus plugin et durcit hello-plugin SDK contre la rechute #120
Requalification Architect du 2026-08-01: le crash INTERFACE INTERROMPUE au chargement d'un plugin (menu + item) remonte via ProjectsView -> usePluginMenus -> MenuBar jusqu'à RootErrorBoundary, quel que soit le plugin (ancien ou reconstruit via SDK). - usePluginMenus isole la résolution/conversion des contributions plugin : toute erreur retombe sur [] au lieu de propager. - ProjectsView sépare les menus natifs des menus enrichis par plugin et rend MenuBar derrière une error boundary locale (fallback menus natifs seuls). - hello-plugin (SDK) et les tests d'installation associés durcis en cohérence. Bookkeeping ticket #120 uniquement (issue.md, carnet.md) ; les fichiers counter.json/index.json et le dossier tickets/122/ restent hors commit car une collision de numérotation #122 existe entre cette base et feature/ticket120-hello-plugin-install-path-audit (deux tickets différents revendiquent #122) — à arbitrer avant de committer le bookkeeping global. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@ -1,15 +1,75 @@
|
||||
import type { ActivateContext, IdeAPluginModule } from "@idea/plugin-sdk";
|
||||
import type { ActivateContext, CommandDisposable, IdeAPluginModule } from "@idea/plugin-sdk";
|
||||
|
||||
const COMMAND_ID = "hello-plugin";
|
||||
const LAYOUT_TYPE = "hello-plugin.hello-world";
|
||||
|
||||
type HelloPluginLayoutProps = {
|
||||
projectId?: string;
|
||||
nodeId?: string;
|
||||
layoutType?: string;
|
||||
state?: unknown;
|
||||
};
|
||||
|
||||
type LayoutRegistry = {
|
||||
register(definition: {
|
||||
type: string;
|
||||
component: (props: HelloPluginLayoutProps) => string;
|
||||
}): CommandDisposable;
|
||||
};
|
||||
|
||||
type HelloPluginContext = ActivateContext & {
|
||||
layouts?: LayoutRegistry;
|
||||
};
|
||||
|
||||
let hasLoggedFirstLayoutRender = false;
|
||||
|
||||
function HelloWorldLayout(props: HelloPluginLayoutProps): string {
|
||||
if (!hasLoggedFirstLayoutRender) {
|
||||
hasLoggedFirstLayoutRender = true;
|
||||
console.info("[hello-plugin] layout first render", {
|
||||
projectId: props.projectId,
|
||||
nodeId: props.nodeId,
|
||||
layoutType: props.layoutType,
|
||||
hasState: props.state !== undefined
|
||||
});
|
||||
}
|
||||
|
||||
return "hello-world";
|
||||
}
|
||||
|
||||
export function activate(ctx: ActivateContext): void {
|
||||
ctx.logger.info("Hello from the IdeA hello plugin.");
|
||||
|
||||
const disposable = ctx.commands?.registerCommand("hello-plugin.sayHello", () => {
|
||||
ctx.logger.info("Hello command executed.");
|
||||
return "Hello from IdeA";
|
||||
const pluginContext = ctx as HelloPluginContext;
|
||||
ctx.logger.info("activating hello-plugin", {
|
||||
pluginId: ctx.pluginId,
|
||||
hasCommands: Boolean(pluginContext.commands),
|
||||
hasLayouts: Boolean(pluginContext.layouts)
|
||||
});
|
||||
|
||||
if (disposable) {
|
||||
ctx.subscriptions.push(disposable);
|
||||
const commandDisposable = pluginContext.commands?.registerCommand(COMMAND_ID, () => {
|
||||
ctx.logger.info("command executed", { commandId: COMMAND_ID });
|
||||
return "hello-world";
|
||||
});
|
||||
|
||||
if (commandDisposable) {
|
||||
ctx.subscriptions.push(commandDisposable);
|
||||
ctx.logger.info("command registered", { commandId: COMMAND_ID });
|
||||
} else {
|
||||
ctx.logger.warn("command registry unavailable", { commandId: COMMAND_ID });
|
||||
}
|
||||
|
||||
const layoutDisposable = pluginContext.layouts?.register({
|
||||
type: LAYOUT_TYPE,
|
||||
component: HelloWorldLayout
|
||||
});
|
||||
|
||||
if (layoutDisposable) {
|
||||
ctx.subscriptions.push(layoutDisposable);
|
||||
ctx.logger.info("layout registered", {
|
||||
layoutType: LAYOUT_TYPE,
|
||||
component: "hello-world"
|
||||
});
|
||||
} else {
|
||||
ctx.logger.warn("layout registry unavailable", { layoutType: LAYOUT_TYPE });
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,4 +78,3 @@ const plugin: IdeAPluginModule = {
|
||||
};
|
||||
|
||||
export default plugin;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user