UNPKG

askeroo

Version:

A modern CLI prompt library with flow control, history navigation, and conditional prompts

136 lines 5.28 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { render } from "ink"; import { PromptApp } from "../components/PromptApp.js"; import { PromptStateProvider } from "./plugin-state-context.js"; import { debugLogger } from "../utils/logging.js"; import { globalRegistry } from "./registry.js"; // Generate stable IDs for prompts based on content and context const generatePromptId = (type, label, groupName) => { const parts = [type, label]; if (groupName) parts.push(`group:${groupName}`); return parts.join("|"); }; let appInstance = {}; function ensureApp() { return new Promise((resolve) => { if (appInstance.promptFn) { resolve(appInstance.promptFn); return; } const { unmount } = render(_jsx(PromptStateProvider, { children: _jsx(PromptApp, { onReady: (promptFn) => { appInstance.promptFn = promptFn; appInstance.unmount = unmount; resolve(promptFn); }, runtime: currentRuntime }) }), { exitOnCtrlC: false, // Prevent Ink from exiting immediately on Ctrl+C }); }); } // Store reference to the runtime for re-discovery and tree access let currentRuntime = null; // Create a dynamic UI object that includes plugin handlers function createUI() { const ui = { /** * Show a group in the UI (called by runtime when executing group plugin) */ async showGroup(label, flow, id, discoveredFields, enableArrowNavigation, depth, parentGroup, groupOptions // Accept all group options including hideOnCompletion ) { const groupId = id || generatePromptId("group", label || "group"); appInstance.currentGroup = groupId; const promptFn = await ensureApp(); // Extract additional options while preserving core properties const { label: _, flow: __, id: ___, enableArrowNavigation: ____, ...additionalOptions } = groupOptions || {}; await promptFn({ type: "group", id: groupId, label: label, flow, discoveredFields, enableArrowNavigation, depth, groupName: parentGroup, // Pass parent group for proper nesting ...additionalOptions, // Spread additional options like hideOnCompletion }); }, clearGroup() { appInstance.currentGroup = undefined; }, cleanup() { if (appInstance.unmount) { debugLogger.log("UI_CLEANUP", "UI cleanup triggered"); appInstance.unmount(); appInstance.promptFn = undefined; appInstance.unmount = undefined; appInstance.currentGroup = undefined; debugLogger.cleanup(); } }, setRuntime(runtime) { currentRuntime = runtime; }, getTreeManager() { // NEW: Expose runtime's tree manager to UI return currentRuntime?.getTree?.() || null; }, async rediscoverStaticGroup(groupId) { if (currentRuntime?.rediscoverStaticGroupFields) { return await currentRuntime.rediscoverStaticGroupFields(groupId); } return null; }, async completeFlow() { const promptFn = await ensureApp(); await promptFn({ type: "completeFlow", id: "flow-completion", }); }, onGroupCompleted(groupId) { // Trigger a re-render by sending a UI update event ensureApp().then((promptFn) => { promptFn({ type: "groupCompleted", id: groupId, }); }); }, }; // Create plugin handlers upfront (no Proxy) for (const plugin of globalRegistry.getAll()) { ui[plugin.type] = async function (opts, currentGroup, id) { // Always update currentGroup, even if it's undefined // This ensures fields outside groups don't inherit the previous group appInstance.currentGroup = typeof currentGroup === "string" ? currentGroup : undefined; const promptFn = await ensureApp(); // Create the request object with all options spread in const request = { type: plugin.type, id: id || generatePromptId(plugin.type, opts.label || `${plugin.type} field`), groupName: appInstance.currentGroup, ...opts, // Spread all options from the plugin }; return promptFn(request); }; } return ui; } // Lazy UI creation to support dynamic plugin registration let uiInstance = null; function ensureUI() { if (!uiInstance) { uiInstance = createUI(); } return uiInstance; } // Export a lightweight Proxy that lazily creates the UI on first access // This allows plugins to register before the UI is created export const ui = new Proxy({}, { get(_target, prop) { return ensureUI()[prop]; }, }); //# sourceMappingURL=ui.js.map