@elementspanel/panel 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app.js +3995 -197
- package/app.js.map +1 -1
- package/package.json +18 -18
- package/public/assets/{AppDialog.vue_vue_type_style_index_0_lang-8b56f871.js → AppDialog.vue_vue_type_style_index_0_lang-e6e38e8b.js} +2 -2
- package/public/assets/AppDialog.vue_vue_type_style_index_0_lang-e6e38e8b.js.map +1 -0
- package/public/assets/CardPanel-59b7da2e.js +2 -0
- package/public/assets/CardPanel-59b7da2e.js.map +1 -0
- package/public/assets/{DesktopDialog-081410ca.js → DesktopDialog-e4041e4e.js} +2 -2
- package/public/assets/DesktopDialog-e4041e4e.js.map +1 -0
- package/public/assets/{Loading.vue_vue_type_script_setup_true_lang-9e79de95.js → Loading.vue_vue_type_script_setup_true_lang-1b74dd54.js} +2 -2
- package/public/assets/Loading.vue_vue_type_script_setup_true_lang-1b74dd54.js.map +1 -0
- package/public/assets/{PageToolbar-5ca1a069.js → PageToolbar-7130e13d.js} +2 -2
- package/public/assets/PageToolbar-7130e13d.js.map +1 -0
- package/public/assets/{_elements-sdk_pinia-fc8ba898.js → _elements-sdk_pinia-2c56d2c1.js} +3 -3
- package/public/assets/{_elements-sdk_pinia-fc8ba898.js.map → _elements-sdk_pinia-2c56d2c1.js.map} +1 -1
- package/public/assets/{_elements-sdk_vue-b86b0db6.js → _elements-sdk_vue-80f42d87.js} +2 -2
- package/public/assets/_elements-sdk_vue-80f42d87.js.map +1 -0
- package/public/assets/{_elements-sdk_vue-i18n-64f8e172.js → _elements-sdk_vue-i18n-4b8a106a.js} +2 -2
- package/public/assets/_elements-sdk_vue-i18n-4b8a106a.js.map +1 -0
- package/public/assets/{_elements-sdk_vue-router-a62f518d.js → _elements-sdk_vue-router-a171591a.js} +2 -2
- package/public/assets/_elements-sdk_vue-router-a171591a.js.map +1 -0
- package/public/assets/{const-cfe7ddfe.js → const-93b324c0.js} +2 -2
- package/public/assets/const-93b324c0.js.map +1 -0
- package/public/assets/{const-01673e6b.js → const-ea30795c.js} +2 -2
- package/public/assets/const-ea30795c.js.map +1 -0
- package/public/assets/{context-b16af9cc.js → context-cc90576e.js} +2 -2
- package/public/assets/{context-b16af9cc.js.map → context-cc90576e.js.map} +1 -1
- package/public/assets/{copy-4d64fc1f.js → copy-b106bb10.js} +2 -2
- package/public/assets/copy-b106bb10.js.map +1 -0
- package/public/assets/{core-b6992169.js → core-d3bfdede.js} +2 -2
- package/public/assets/core-d3bfdede.js.map +1 -0
- package/public/assets/{desktopNotice-2c886f6b.js → desktopNotice-5ca3448c.js} +2 -2
- package/public/assets/desktopNotice-5ca3448c.js.map +1 -0
- package/public/assets/dom-ff483262.js.map +1 -1
- package/public/assets/{i18n-fe0f1ee7.js → i18n-e810b9fa.js} +2 -2
- package/public/assets/i18n-e810b9fa.js.map +1 -0
- package/public/assets/index-1da88aed.js +2 -0
- package/public/assets/index-1da88aed.js.map +1 -0
- package/public/assets/index-e3f35709.js.map +1 -1
- package/public/assets/{instance-26cca4c8.js → instance-cc59e210.js} +2 -2
- package/public/assets/instance-cc59e210.js.map +1 -0
- package/public/assets/lodash-001e4f93.js.map +1 -1
- package/public/assets/{nodes-402cdcbd.js → nodes-a56b1b35.js} +2 -2
- package/public/assets/nodes-a56b1b35.js.map +1 -0
- package/public/assets/protocol-97f7bab7.js.map +1 -1
- package/public/assets/randId-56f93901.js +2 -0
- package/public/assets/randId-56f93901.js.map +1 -0
- package/public/assets/{router-0f7d4714.js → router-eff205cc.js} +2 -2
- package/public/assets/router-eff205cc.js.map +1 -0
- package/public/assets/safe-87846d89.js.map +1 -1
- package/public/assets/{sdk-01dda668.js → sdk-3f2277ab.js} +2 -2
- package/public/assets/sdk-3f2277ab.js.map +1 -0
- package/public/assets/{shared-f2e37690.js → shared-597ef52b.js} +2 -2
- package/public/assets/shared-597ef52b.js.map +1 -0
- package/public/assets/{useAppConfigStore-289073ec.js → useAppConfigStore-352fe033.js} +2 -2
- package/public/assets/useAppConfigStore-352fe033.js.map +1 -0
- package/public/assets/useAppRouters-747b627a.js +2 -0
- package/public/assets/useAppRouters-747b627a.js.map +1 -0
- package/public/assets/{useAppStateStore-a644582a.js → useAppStateStore-a438b9a6.js} +2 -2
- package/public/assets/useAppStateStore-a438b9a6.js.map +1 -0
- package/public/assets/{useAppToolsStore-3a911226.js → useAppToolsStore-288c4fe8.js} +2 -2
- package/public/assets/useAppToolsStore-288c4fe8.js.map +1 -0
- package/public/assets/{useDefineApi-ead2616e.js → useDefineApi-b726db1e.js} +2 -2
- package/public/assets/useDefineApi-b726db1e.js.map +1 -0
- package/public/assets/{useInstanceActionAvailability-dec16c10.js → useInstanceActionAvailability-16de3001.js} +2 -2
- package/public/assets/useInstanceActionAvailability-16de3001.js.map +1 -0
- package/public/assets/{useKeyboardEvents-dba9d5ca.js → useKeyboardEvents-6f7f845c.js} +2 -2
- package/public/assets/useKeyboardEvents-6f7f845c.js.map +1 -0
- package/public/assets/{useMountComponent-dd1fcfea.js → useMountComponent-4043cb4c.js} +2 -2
- package/public/assets/useMountComponent-4043cb4c.js.map +1 -0
- package/public/assets/{useOverviewChart-119bda3b.js → useOverviewChart-7d758bc4.js} +2 -2
- package/public/assets/useOverviewChart-7d758bc4.js.map +1 -0
- package/public/assets/{useOverviewInfo-a149d634.js → useOverviewInfo-9ca25ab9.js} +2 -2
- package/public/assets/useOverviewInfo-9ca25ab9.js.map +1 -0
- package/public/assets/{usePolling-f2f09d27.js → usePolling-1bc2009b.js} +2 -2
- package/public/assets/usePolling-1bc2009b.js.map +1 -0
- package/public/assets/{useScreen-e3715e1f.js → useScreen-fad29b7c.js} +2 -2
- package/public/assets/useScreen-fad29b7c.js.map +1 -0
- package/public/assets/{useSocketIo-bc0a62c2.js → useSocketIo-ea3c9a61.js} +2 -2
- package/public/assets/useSocketIo-ea3c9a61.js.map +1 -0
- package/public/assets/{useThemeSwitch-6ff90248.js → useThemeSwitch-dc70883c.js} +2 -2
- package/public/assets/useThemeSwitch-dc70883c.js.map +1 -0
- package/public/assets/{vue-2433bd89.js → vue-6b52a630.js} +2 -2
- package/public/assets/{vue-2433bd89.js.map → vue-6b52a630.js.map} +1 -1
- package/public/assets/{vuetifyModal-49cb95ba.js → vuetifyModal-8382b175.js} +2 -2
- package/public/assets/vuetifyModal-8382b175.js.map +1 -0
- package/public/index.html +4 -4
- package/public/stats.html +2 -2
- package/runtime/npm-plugins.cjs +49 -13
- package/runtime/plugin-resolution.cjs +27 -9
- package/public/assets/AppDialog.vue_vue_type_style_index_0_lang-8b56f871.js.map +0 -1
- package/public/assets/CardPanel-a704f146.js +0 -2
- package/public/assets/CardPanel-a704f146.js.map +0 -1
- package/public/assets/DesktopDialog-081410ca.js.map +0 -1
- package/public/assets/Loading.vue_vue_type_script_setup_true_lang-9e79de95.js.map +0 -1
- package/public/assets/PageToolbar-5ca1a069.js.map +0 -1
- package/public/assets/_elements-sdk_vue-b86b0db6.js.map +0 -1
- package/public/assets/_elements-sdk_vue-i18n-64f8e172.js.map +0 -1
- package/public/assets/_elements-sdk_vue-router-a62f518d.js.map +0 -1
- package/public/assets/const-01673e6b.js.map +0 -1
- package/public/assets/const-cfe7ddfe.js.map +0 -1
- package/public/assets/copy-4d64fc1f.js.map +0 -1
- package/public/assets/core-b6992169.js.map +0 -1
- package/public/assets/desktopNotice-2c886f6b.js.map +0 -1
- package/public/assets/i18n-fe0f1ee7.js.map +0 -1
- package/public/assets/index-76b0df52.js +0 -2
- package/public/assets/index-76b0df52.js.map +0 -1
- package/public/assets/instance-26cca4c8.js.map +0 -1
- package/public/assets/nodes-402cdcbd.js.map +0 -1
- package/public/assets/randId-ed0b95b7.js +0 -2
- package/public/assets/randId-ed0b95b7.js.map +0 -1
- package/public/assets/router-0f7d4714.js.map +0 -1
- package/public/assets/sdk-01dda668.js.map +0 -1
- package/public/assets/shared-f2e37690.js.map +0 -1
- package/public/assets/useAppConfigStore-289073ec.js.map +0 -1
- package/public/assets/useAppRouters-5f58db32.js +0 -2
- package/public/assets/useAppRouters-5f58db32.js.map +0 -1
- package/public/assets/useAppStateStore-a644582a.js.map +0 -1
- package/public/assets/useAppToolsStore-3a911226.js.map +0 -1
- package/public/assets/useDefineApi-ead2616e.js.map +0 -1
- package/public/assets/useInstanceActionAvailability-dec16c10.js.map +0 -1
- package/public/assets/useKeyboardEvents-dba9d5ca.js.map +0 -1
- package/public/assets/useMountComponent-dd1fcfea.js.map +0 -1
- package/public/assets/useOverviewChart-119bda3b.js.map +0 -1
- package/public/assets/useOverviewInfo-a149d634.js.map +0 -1
- package/public/assets/usePolling-f2f09d27.js.map +0 -1
- package/public/assets/useScreen-e3715e1f.js.map +0 -1
- package/public/assets/useSocketIo-bc0a62c2.js.map +0 -1
- package/public/assets/useThemeSwitch-6ff90248.js.map +0 -1
- package/public/assets/vuetifyModal-49cb95ba.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-b16af9cc.js","sources":["../../src/plugin/context.ts"],"sourcesContent":["import { Context } from \"cordis\";\nimport { shallowRef, type App, type Component } from \"vue\";\nimport type { Pinia } from \"pinia\";\nimport type { RouteRecordRaw, Router } from \"vue-router\";\nimport type { I18n } from \"vue-i18n\";\nimport type { RemoteNodeHook } from \"@console/hooks/useRemoteNode\";\nimport type { NodePluginApi } from \"@console/services/apis/node\";\nimport type { UserPluginApi } from \"@console/services/apis/user\";\nimport type { LoadedPanelFrontendPlugin, PanelFrontendPluginMetadata } from \"./loader\";\nimport type { PluginState } from \"../../../common/src/plugin_contract\";\n\n/**\n * The frontend's cordis container, and the complete list of what a plugin can\n * see.\n *\n * Every capability is a service on the context; every registration a plugin\n * makes is an effect owned by that plugin's scope, so unloading a plugin undoes\n * its routes, cards, menus, actions and translations without the plugin writing\n * any cleanup code. `ctx.logger` and the timer helpers come with cordis itself.\n *\n * Keep this module import-light. Panel code that only needs to resolve a\n * plugin-provided service — `services/apis/user.ts`, say — imports it, and\n * pulling the card and route registries in here would drag every widget into the\n * app entry graph and create an import cycle with `@/lang/i18n`.\n */\nexport const ctx = new Context();\n\n/**\n * Bumped whenever any service appears or disappears. A `computed()` that reads\n * a plugin-provided service must read this first, or it will not re-evaluate\n * when the owning plugin is loaded or unloaded — cordis's registry is not a Vue\n * reactive source.\n */\nexport const serviceRevision = shallowRef(0);\nctx.on(\"internal/service\", () => {\n serviceRevision.value += 1;\n});\n\n/**\n * Resolve a service a plugin may or may not provide, reactively. Returns\n * `undefined` when nothing provides it, so callers degrade instead of throwing.\n */\nexport function usePluginService<T>(name: string): T | undefined {\n void serviceRevision.value;\n return ctx.get(name as never) as T | undefined;\n}\n\nexport interface PanelFrontendLoginAction {\n title: string | (() => string);\n icon?: Component | string;\n click: () => unknown;\n condition?: boolean | (() => boolean);\n}\n\nexport interface PanelFrontendDesktopApp {\n id: string;\n label: string | (() => string);\n icon: Component | string;\n color?: string;\n route?: string;\n component?: Component;\n condition?: boolean | (() => boolean);\n initialWidth?: number;\n initialHeight?: number;\n /** Registered view id, also used to restore saved windows. */\n view?: string;\n}\n\nexport interface PanelFrontendDesktopView {\n id: string;\n component: Component;\n title: string | (() => string);\n icon: string;\n initialWidth?: number;\n initialHeight?: number;\n condition?: () => boolean;\n accepts?: (props: Record<string, unknown>) => boolean;\n}\n\nexport interface PanelFrontendDesktopWindowRequest {\n id: string;\n view: string;\n title?: string;\n props?: Record<string, unknown>;\n}\n\nexport interface PanelFrontendInstanceActionContext {\n mode: \"normal\" | \"desktop\";\n instanceId: string;\n daemonId: string;\n instanceInfo: unknown;\n daemon?: unknown;\n isGlobalTerminal: boolean;\n}\n\nexport interface PanelFrontendInstanceAction {\n id: string;\n title: string | (() => string);\n icon: Component | string;\n /** Material Design icon rendered by the panel shells. */\n mdiIcon: string;\n normalComponent?: Component;\n desktopComponent?: Component;\n condition?: (context: PanelFrontendInstanceActionContext) => boolean;\n desktopInitialWidth?: number;\n desktopInitialHeight?: number;\n}\n\nexport interface PanelFrontendScheduleAction {\n type: string;\n title: string | (() => string);\n inputPlaceholder?: string | (() => string);\n condition?: () => boolean;\n}\n\n/**\n * State a terminal action's `click` and `condition` are given. It mirrors what\n * the terminal itself knows about the instance in front of the user, so a plugin\n * button behaves the same in the normal terminal and in a Desktop console.\n */\nexport interface PanelFrontendTerminalActionContext {\n mode: \"normal\" | \"desktop\";\n instanceId: string;\n daemonId: string;\n instanceInfo: unknown;\n isStopped: boolean;\n isRunning: boolean;\n isGlobalTerminal: boolean;\n isDockerMode: boolean;\n clearTerminal: () => void;\n}\n\n/** A button a plugin adds to the terminal's instance-operations row. */\nexport interface PanelFrontendTerminalAction {\n id: string;\n title: string | (() => string);\n icon: Component | string;\n /** Material Design icon rendered by the panel shells. */\n mdiIcon: string;\n /** Matches the core buttons: \"default\" | \"danger\". */\n type?: string;\n class?: string;\n noConfirm?: boolean;\n props?: Record<string, unknown>;\n click: (context: PanelFrontendTerminalActionContext) => unknown;\n condition?: (context: PanelFrontendTerminalActionContext) => boolean;\n}\n\n/** The button descriptor both terminals render. */\nexport interface PanelFrontendTerminalButton {\n id: string;\n title: string;\n icon: Component | string;\n mdiIcon: string;\n type: string;\n class?: string;\n noConfirm: boolean;\n props: Record<string, unknown>;\n click: () => unknown;\n condition: () => boolean;\n}\n\n/** The Vue application a plugin registers into. Stored raw, never reactive. */\nexport interface FrontendVueService {\n readonly app: App;\n readonly pinia: Pinia;\n readonly router: Router;\n}\n\n/** Startup state and errors. Provided by the foundational `runtime` plugin. */\nexport interface FrontendStartupService {\n readonly language: string;\n showError(error: unknown): void;\n}\n\n/** The panel shell. Provided by the foundational `console` plugin. */\nexport interface FrontendConsoleService {\n readonly root: Component;\n}\n\nexport interface PanelLanguageOption {\n label: string;\n value: string;\n}\n\nexport interface FrontendI18nService {\n readonly instance: I18n;\n readonly supportedLanguages: readonly PanelLanguageOption[];\n getSupportLanguages(): string[];\n searchSupportLanguage(language: string): string;\n getCurrentLang(): string;\n setLanguage(language: string, reload?: boolean): void;\n isCN(): boolean;\n isEN(): boolean;\n translate(...args: any[]): string;\n /**\n * Merge the plugin's translations, keyed by locale (`en_us`, `zh_cn`, ...).\n * The base catalogue is snapshotted and re-applied on unload, so a plugin's\n * strings — including any that override a core string — leave with it.\n */\n define(messages: Record<string, Record<string, unknown>>): () => void;\n}\n\nexport interface FrontendRoutesService {\n /** Adds a route, removed again when the calling plugin unloads. */\n add(route: RouteRecordRaw): () => void;\n /** Read inside a `computed()` that enumerates routes, to make it reactive. */\n readonly revision: number;\n /** Whether a path belongs to a plugin rather than to the core. */\n isPluginRoute(path: string): boolean;\n /** The name of the plugin that added a path, if a plugin did. */\n ownerOf(path: string): string | undefined;\n}\n\nexport interface FrontendUiService {\n /** Registers a global component; a previous registration is restored on unload. */\n component(name: string, component: Component): () => void;\n /**\n * Mounts a component for the lifetime of the plugin, alongside the panel's own\n * dialog providers. For global overlays that belong to no route.\n */\n globalComponent(component: Component): () => void;\n readonly globalComponents: readonly Component[];\n}\n\n/** Slots owned by the console shell and available to independently loaded plugins. */\nexport interface PanelFrontendSlotMap {\n \"shell.overlay\": { props: Record<string, never> };\n \"shell.header.leading\": { props: { mobile: boolean } };\n \"shell.header.actions\": { props: { mobile: boolean } };\n}\n\nexport type PanelFrontendSlotName = keyof PanelFrontendSlotMap & string;\nexport type PanelFrontendSlotProps<K extends PanelFrontendSlotName> =\n PanelFrontendSlotMap[K][\"props\"];\n\n/**\n * A declarative header button. The shell owns the button, tooltip and badge\n * styling, so plugins only describe the icon, label and action.\n */\nexport interface PanelFrontendHeaderAction {\n /** Tooltip and accessible label text. */\n title: string | (() => string);\n /** MDI icon rendered by the shell; a function keeps it reactive. */\n mdiIcon: string | (() => string);\n /** Badge text; `false`, `null` and `undefined` hide the badge. */\n badge?: string | number | (() => string | number | undefined | null | false);\n click: (...args: any[]) => unknown;\n /** Overrides `click` in the Desktop taskbar tray. */\n desktopClick?: () => unknown;\n /** Extra class for the shell button, e.g. `nav-button-danger`. */\n customClass?: string | string[];\n /** Hide in the phone header. */\n onlyPC?: boolean;\n /** Also render in the Desktop taskbar tray. Defaults to true. */\n taskbar?: boolean;\n /** ARIA controls target for toggle buttons. */\n ariaControls?: string;\n /** Current toggle state, for `aria-expanded` and pressed styling. */\n expanded?: () => boolean;\n /** Changing value restarts a one-shot ripple around the button. */\n ripple?: () => number | undefined;\n}\n\nexport interface PanelFrontendSlotEntry<K extends PanelFrontendSlotName = PanelFrontendSlotName> {\n readonly id: string;\n readonly owner: string;\n readonly name: K;\n readonly component?: Component;\n readonly action?: PanelFrontendHeaderAction;\n readonly order: number;\n readonly props: Record<string, unknown>;\n}\n\nexport interface PanelFrontendSlotRegistration<K extends PanelFrontendSlotName> {\n /** Stable identity inside one slot. Defaults to `<plugin>:<sequence>`. */\n id?: string;\n /** Lower values render first. */\n order?: number;\n /** Static props merged after the shell-owned props. */\n props?: Record<string, unknown>;\n /** Evaluated whenever the shell enumerates the slot. */\n condition?: (props: PanelFrontendSlotProps<K>) => boolean;\n}\n\nexport interface FrontendSlotsService {\n /** Header action seat: pass a descriptor and the shell renders the button. */\n register(\n name: \"shell.header.actions\",\n action: PanelFrontendHeaderAction,\n options?: PanelFrontendSlotRegistration<\"shell.header.actions\">\n ): () => void;\n register<K extends PanelFrontendSlotName>(\n name: K,\n component: Component,\n options?: PanelFrontendSlotRegistration<K>\n ): () => void;\n entries<K extends PanelFrontendSlotName>(\n name: K,\n props: PanelFrontendSlotProps<K>\n ): readonly PanelFrontendSlotEntry<K>[];\n}\n\nexport interface FrontendMenusService {\n login(action: PanelFrontendLoginAction): () => void;\n readonly loginActions: readonly PanelFrontendLoginAction[];\n}\n\nexport interface FrontendActionsService {\n instance(action: PanelFrontendInstanceAction): () => void;\n schedule(action: PanelFrontendScheduleAction): () => void;\n terminal(action: PanelFrontendTerminalAction): () => void;\n readonly instances: readonly PanelFrontendInstanceAction[];\n readonly schedules: readonly PanelFrontendScheduleAction[];\n readonly terminals: readonly PanelFrontendTerminalAction[];\n /**\n * The registered terminal actions as the button descriptors both terminals\n * already render, so neither call site has to know how a registration looks.\n */\n terminalButtons(state: PanelFrontendTerminalActionContext): PanelFrontendTerminalButton[];\n}\n\nexport interface FrontendPluginsService {\n readonly loaded: readonly LoadedPanelFrontendPlugin[];\n readonly diagnostics: readonly PanelFrontendPluginDiagnostic[];\n load(id: string): Promise<LoadedPanelFrontendPlugin>;\n unload(id: string): Promise<boolean>;\n reload(id: string): Promise<LoadedPanelFrontendPlugin>;\n /** Re-reads the installed plugins and loads or unloads to match. */\n refresh(): Promise<readonly PanelFrontendPluginMetadata[]>;\n /** Throws only when an entry declared `frontendRequired` is not active. */\n audit(): void;\n}\n\nexport interface PanelFrontendPluginDiagnostic {\n id: string;\n state: PluginState;\n required: boolean;\n revision?: string;\n requiredServices: readonly string[];\n missingServices: readonly string[];\n error?: string;\n}\n\nexport type FrontendConnectionStatus =\n | \"connecting\"\n | \"connected\"\n | \"degraded\"\n | \"disconnected\";\n\nexport interface FrontendConnectionState {\n status: FrontendConnectionStatus;\n networkAvailable: boolean;\n generation: number;\n retryAttempt: number;\n lastError?: string;\n changedAt: number;\n}\n\nexport interface FrontendConnectionService {\n readonly state: Readonly<FrontendConnectionState>;\n /** Cancels the current retry delay and probes the panel immediately. */\n reconnect(): void;\n}\n\n/**\n * Desktop mode's application registry.\n *\n * Supplied by the console plugin even though Desktop mode is optional. An\n * application belongs to whichever plugin owns the page and is disposed with\n * that plugin rather than with Desktop. Without `plugins/desktop` nothing renders\n * the registry and `window` is absent.\n */\nexport interface FrontendDesktopService {\n /** Adds an application to the Desktop, removed when the calling plugin unloads. */\n app(desktopApp: PanelFrontendDesktopApp): () => void;\n readonly apps: readonly PanelFrontendDesktopApp[];\n view(view: PanelFrontendDesktopView): () => void;\n readonly views: readonly PanelFrontendDesktopView[];\n open(request: PanelFrontendDesktopWindowRequest): boolean;\n provideOpener(open: (request: PanelFrontendDesktopWindowRequest) => boolean): () => void;\n /** The window shell a Desktop-mode component is mounted inside. */\n readonly window: Component | undefined;\n /** Supplies that shell. Called by `plugins/desktop`. */\n provideWindow(component: Component): () => void;\n /** The shared confirmation window supplied by `plugins/desktop`. */\n readonly confirmation: Component | undefined;\n provideConfirmation(component: Component): () => void;\n}\n\n/**\n * The file manager. Provided by `plugins/file`.\n *\n * It publishes more than a page: the upload queue the settings page and the\n * create-instance form drive, the file editor the mod manager and the backup\n * plugin open, the dialogs the panel mounts on demand, and the filename helpers\n * the code editor and archive preview use. Every consumer resolves it with\n * `usePluginService` and degrades when the plugin is absent.\n */\nexport interface FrontendFileManagerService {\n readonly api: Record<string, unknown>;\n readonly useFileManager: (...args: any[]) => any;\n readonly getFileConfigAddr: (...args: any[]) => any;\n readonly uploadService: any;\n readonly UploadFiles: any;\n readonly getFileIcon: (fileName: string, type?: number) => string;\n readonly getFileExtName: (fileName: string) => string;\n readonly filterFileName: (fileName: string) => string;\n readonly isCompressFile: (fileName: string) => boolean;\n readonly FileEditor: Component;\n readonly ImageViewer: Component;\n readonly DesktopFileManager: Component;\n readonly DesktopFileEditor: Component;\n readonly DesktopImageViewer: Component;\n useUploadFileDialog(): Promise<string>;\n useDownloadFileDialog(): Promise<any>;\n useImageViewerDialog(\n instanceId: string,\n daemonId: string,\n fileName: string,\n frontDir: string\n ): Promise<any>;\n}\n\n/** The instance terminal and its stream client. Provided by `plugins/terminal`. */\nexport interface FrontendTerminalService {\n readonly api: Record<string, unknown>;\n readonly TerminalCore: Component;\n readonly TerminalTags: Component;\n readonly TerminalTopTags: Component;\n readonly useTerminal: (...args: any[]) => any;\n readonly useCommandHistory: (...args: any[]) => any;\n readonly encodeConsoleColor: (text: string) => string;\n}\n\n/** Minecraft mod and plugin APIs. Provided by `plugins/mod`. */\nexport interface FrontendModManagerService {\n readonly api: typeof import(\"../../../panel/plugins/mod/src/api\");\n}\n\n/** Java environment selector supplied by `plugins/instance`. */\nexport interface FrontendJavaService {\n readonly setupComponent: Component;\n}\n\n/** Application instance pages, APIs, hooks and dialogs. Provided by `plugins/instance`. */\nexport interface FrontendInstanceService {\n readonly api: Record<string, (...args: any[]) => any>;\n openConsole(instance: unknown, daemonId: string): boolean;\n readonly hooks: typeof import(\"../../../panel/plugins/instance/src/hooks/useInstance\") &\n typeof import(\"../../../panel/plugins/instance/src/hooks/useInstanceTag\") &\n typeof import(\"../../../panel/plugins/instance/src/hooks/quickStartFlow\") & {\n useSchedule: typeof import(\"../../../panel/plugins/instance/src/hooks/useSchedule\").useSchedule;\n useServerConfig: typeof import(\"../../../panel/plugins/instance/src/hooks/useServerConfig\").useServerConfig;\n useStartCmdBuilder: typeof import(\"../../../panel/plugins/instance/src/hooks/useGenerateStartCmd\").useStartCmdBuilder;\n };\n readonly components: {\n readonly CmdAssistantDialog: Component;\n readonly CreateInstanceForm: Component;\n readonly InstanceDetail: Component;\n readonly DeleteInstanceDialog: Component;\n readonly DockerCapabilityDialog: Component;\n readonly DockerDeviceDialog: Component;\n readonly DockerPortDialog: Component;\n readonly DockerVersionSelectDialog: Component;\n readonly NodeSelectDialog: Component;\n readonly SelectInstances: Component;\n readonly TagsDialog: Component;\n };\n}\n\n/** Accounts and sessions. Provided by `plugins/user`. */\nexport interface FrontendUserService {\n restoreSession(): Promise<void>;\n readonly api: UserPluginApi;\n readonly desktopLoginWindow: Component;\n readonly desktopUsers: Component;\n readonly desktopUserInfo: Component;\n readonly desktopStartMenuAvatar: Component;\n}\n\n/** The app market service supplied by an installed market plugin. */\nexport interface FrontendMarketService {\n readonly api: Record<string, unknown>;\n openMarketDialog(\n daemonId?: string,\n instanceId?: string,\n options?: { autoInstall?: boolean; onlyDockerTemplate?: boolean }\n ): Promise<unknown>;\n useMarketPackages(options?: Record<string, unknown>): unknown;\n}\n\n/** Node management. Provided by `plugins/node`. */\nexport interface FrontendNodeService {\n readonly api: NodePluginApi;\n useRemoteNode(): RemoteNodeHook;\n}\n\ndeclare module \"cordis\" {\n interface Events {\n \"plugins/loaded\"(): void | Promise<void>;\n }\n\n interface Context {\n startup: FrontendStartupService;\n // Services provided by the foundational frontend plugins.\n vue: FrontendVueService;\n console: FrontendConsoleService;\n // Provided first by the foundational `i18n` plugin.\n i18n: FrontendI18nService;\n routes: FrontendRoutesService;\n ui: FrontendUiService;\n slots: FrontendSlotsService;\n menus: FrontendMenusService;\n actions: FrontendActionsService;\n plugins: FrontendPluginsService;\n desktop: FrontendDesktopService;\n connection: FrontendConnectionService;\n\n // Provided by plugins. Read them with `usePluginService()` for graceful\n // degradation, or `inject` them from a plugin that cannot work without one.\n user: FrontendUserService;\n market: FrontendMarketService;\n node: FrontendNodeService;\n instance: FrontendInstanceService;\n mod: FrontendModManagerService;\n java: FrontendJavaService;\n file: FrontendFileManagerService;\n terminal: FrontendTerminalService;\n }\n}\n\n/** The context a frontend plugin's `apply()` receives. */\nexport type PanelFrontendPluginContext = Context;\n"],"names":["ctx","Context","serviceRevision","shallowRef","usePluginService","name"],"mappings":"8FAyBa,MAAAA,EAAM,IAAIC,EAQVC,EAAkBC,EAAW,CAAC,EAC3CH,EAAI,GAAG,mBAAoB,IAAM,CAC/BE,EAAgB,OAAS,CAC3B,CAAC,EAMM,SAASE,EAAoBC,EAA6B,CAC/D,OAAKH,EAAgB,MACdF,EAAI,IAAIK,CAAa,CAC9B"}
|
|
1
|
+
{"version":3,"file":"context-cc90576e.js","sources":["../../src/plugin/context.ts"],"sourcesContent":["import { Context } from \"cordis\";\nimport { shallowRef, type App, type Component } from \"vue\";\nimport type { Pinia } from \"pinia\";\nimport type { RouteRecordRaw, Router } from \"vue-router\";\nimport type { I18n } from \"vue-i18n\";\nimport type { RemoteNodeHook } from \"@console/hooks/useRemoteNode\";\nimport type { NodePluginApi } from \"@console/services/apis/node\";\nimport type { UserPluginApi } from \"@console/services/apis/user\";\nimport type { LoadedPanelFrontendPlugin, PanelFrontendPluginMetadata } from \"./loader\";\nimport type { PluginState } from \"../../../common/src/plugin_contract\";\n\n/**\n * The frontend's cordis container, and the complete list of what a plugin can\n * see.\n *\n * Every capability is a service on the context; every registration a plugin\n * makes is an effect owned by that plugin's scope, so unloading a plugin undoes\n * its routes, cards, menus, actions and translations without the plugin writing\n * any cleanup code. `ctx.logger` and the timer helpers come with cordis itself.\n *\n * Keep this module import-light. Panel code that only needs to resolve a\n * plugin-provided service — `services/apis/user.ts`, say — imports it, and\n * pulling the card and route registries in here would drag every widget into the\n * app entry graph and create an import cycle with `@/lang/i18n`.\n */\nexport const ctx = new Context();\n\n/**\n * Bumped whenever any service appears or disappears. A `computed()` that reads\n * a plugin-provided service must read this first, or it will not re-evaluate\n * when the owning plugin is loaded or unloaded — cordis's registry is not a Vue\n * reactive source.\n */\nexport const serviceRevision = shallowRef(0);\nctx.on(\"internal/service\", () => {\n serviceRevision.value += 1;\n});\n\n/**\n * Resolve a service a plugin may or may not provide, reactively. Returns\n * `undefined` when nothing provides it, so callers degrade instead of throwing.\n */\nexport function usePluginService<T>(name: string): T | undefined {\n void serviceRevision.value;\n return ctx.get(name as never) as T | undefined;\n}\n\nexport interface PanelFrontendLoginAction {\n title: string | (() => string);\n icon?: Component | string;\n click: () => unknown;\n condition?: boolean | (() => boolean);\n}\n\nexport interface PanelFrontendDesktopApp {\n id: string;\n label: string | (() => string);\n icon: Component | string;\n color?: string;\n route?: string;\n component?: Component;\n condition?: boolean | (() => boolean);\n initialWidth?: number;\n initialHeight?: number;\n /** Registered view id, also used to restore saved windows. */\n view?: string;\n}\n\nexport interface PanelFrontendDesktopView {\n id: string;\n component: Component;\n title: string | (() => string);\n icon: string;\n initialWidth?: number;\n initialHeight?: number;\n condition?: () => boolean;\n accepts?: (props: Record<string, unknown>) => boolean;\n}\n\nexport interface PanelFrontendDesktopWindowRequest {\n id: string;\n view: string;\n title?: string;\n props?: Record<string, unknown>;\n}\n\nexport interface PanelFrontendInstanceActionContext {\n mode: \"normal\" | \"desktop\";\n instanceId: string;\n daemonId: string;\n instanceInfo: unknown;\n daemon?: unknown;\n isGlobalTerminal: boolean;\n}\n\nexport interface PanelFrontendInstanceAction {\n id: string;\n title: string | (() => string);\n icon: Component | string;\n /** Material Design icon rendered by the panel shells. */\n mdiIcon: string;\n normalComponent?: Component;\n desktopComponent?: Component;\n condition?: (context: PanelFrontendInstanceActionContext) => boolean;\n desktopInitialWidth?: number;\n desktopInitialHeight?: number;\n}\n\nexport interface PanelFrontendScheduleAction {\n type: string;\n title: string | (() => string);\n inputPlaceholder?: string | (() => string);\n condition?: () => boolean;\n}\n\n/**\n * State a terminal action's `click` and `condition` are given. It mirrors what\n * the terminal itself knows about the instance in front of the user, so a plugin\n * button behaves the same in the normal terminal and in a Desktop console.\n */\nexport interface PanelFrontendTerminalActionContext {\n mode: \"normal\" | \"desktop\";\n instanceId: string;\n daemonId: string;\n instanceInfo: unknown;\n isStopped: boolean;\n isRunning: boolean;\n isGlobalTerminal: boolean;\n isDockerMode: boolean;\n clearTerminal: () => void;\n}\n\n/** A button a plugin adds to the terminal's instance-operations row. */\nexport interface PanelFrontendTerminalAction {\n id: string;\n title: string | (() => string);\n icon: Component | string;\n /** Material Design icon rendered by the panel shells. */\n mdiIcon: string;\n /** Matches the core buttons: \"default\" | \"danger\". */\n type?: string;\n class?: string;\n noConfirm?: boolean;\n props?: Record<string, unknown>;\n click: (context: PanelFrontendTerminalActionContext) => unknown;\n condition?: (context: PanelFrontendTerminalActionContext) => boolean;\n}\n\n/** The button descriptor both terminals render. */\nexport interface PanelFrontendTerminalButton {\n id: string;\n title: string;\n icon: Component | string;\n mdiIcon: string;\n type: string;\n class?: string;\n noConfirm: boolean;\n props: Record<string, unknown>;\n click: () => unknown;\n condition: () => boolean;\n}\n\n/** The Vue application a plugin registers into. Stored raw, never reactive. */\nexport interface FrontendVueService {\n readonly app: App;\n readonly pinia: Pinia;\n readonly router: Router;\n}\n\n/** Startup state and errors. Provided by the foundational `runtime` plugin. */\nexport interface FrontendStartupService {\n readonly language: string;\n showError(error: unknown): void;\n}\n\n/** The panel shell. Provided by the foundational `console` plugin. */\nexport interface FrontendConsoleService {\n readonly root: Component;\n}\n\nexport interface PanelLanguageOption {\n label: string;\n value: string;\n}\n\nexport interface FrontendI18nService {\n readonly instance: I18n;\n readonly supportedLanguages: readonly PanelLanguageOption[];\n getSupportLanguages(): string[];\n searchSupportLanguage(language: string): string;\n getCurrentLang(): string;\n setLanguage(language: string, reload?: boolean): void;\n isCN(): boolean;\n isEN(): boolean;\n translate(...args: any[]): string;\n /**\n * Merge the plugin's translations, keyed by locale (`en_us`, `zh_cn`, ...).\n * The base catalogue is snapshotted and re-applied on unload, so a plugin's\n * strings — including any that override a core string — leave with it.\n */\n define(messages: Record<string, Record<string, unknown>>): () => void;\n}\n\nexport interface FrontendRoutesService {\n /** Adds a route, removed again when the calling plugin unloads. */\n add(route: RouteRecordRaw): () => void;\n /** Read inside a `computed()` that enumerates routes, to make it reactive. */\n readonly revision: number;\n /** Whether a path belongs to a plugin rather than to the core. */\n isPluginRoute(path: string): boolean;\n /** The name of the plugin that added a path, if a plugin did. */\n ownerOf(path: string): string | undefined;\n}\n\nexport interface FrontendUiService {\n /** Registers a global component; a previous registration is restored on unload. */\n component(name: string, component: Component): () => void;\n /**\n * Mounts a component for the lifetime of the plugin, alongside the panel's own\n * dialog providers. For global overlays that belong to no route.\n */\n globalComponent(component: Component): () => void;\n readonly globalComponents: readonly Component[];\n}\n\n/** Slots owned by the console shell and available to independently loaded plugins. */\nexport interface PanelFrontendSlotMap {\n \"shell.overlay\": { props: Record<string, never> };\n \"shell.header.leading\": { props: { mobile: boolean } };\n \"shell.header.actions\": { props: { mobile: boolean } };\n}\n\nexport type PanelFrontendSlotName = keyof PanelFrontendSlotMap & string;\nexport type PanelFrontendSlotProps<K extends PanelFrontendSlotName> =\n PanelFrontendSlotMap[K][\"props\"];\n\n/**\n * A declarative header button. The shell owns the button, tooltip and badge\n * styling, so plugins only describe the icon, label and action.\n */\nexport interface PanelFrontendHeaderAction {\n /** Tooltip and accessible label text. */\n title: string | (() => string);\n /** MDI icon rendered by the shell; a function keeps it reactive. */\n mdiIcon: string | (() => string);\n /** Badge text; `false`, `null` and `undefined` hide the badge. */\n badge?: string | number | (() => string | number | undefined | null | false);\n click: (...args: any[]) => unknown;\n /** Overrides `click` in the Desktop taskbar tray. */\n desktopClick?: () => unknown;\n /** Extra class for the shell button, e.g. `nav-button-danger`. */\n customClass?: string | string[];\n /** Hide in the phone header. */\n onlyPC?: boolean;\n /** Also render in the Desktop taskbar tray. Defaults to true. */\n taskbar?: boolean;\n /** ARIA controls target for toggle buttons. */\n ariaControls?: string;\n /** Current toggle state, for `aria-expanded` and pressed styling. */\n expanded?: () => boolean;\n /** Changing value restarts a one-shot ripple around the button. */\n ripple?: () => number | undefined;\n}\n\nexport interface PanelFrontendSlotEntry<K extends PanelFrontendSlotName = PanelFrontendSlotName> {\n readonly id: string;\n readonly owner: string;\n readonly name: K;\n readonly component?: Component;\n readonly action?: PanelFrontendHeaderAction;\n readonly order: number;\n readonly props: Record<string, unknown>;\n}\n\nexport interface PanelFrontendSlotRegistration<K extends PanelFrontendSlotName> {\n /** Stable identity inside one slot. Defaults to `<plugin>:<sequence>`. */\n id?: string;\n /** Lower values render first. */\n order?: number;\n /** Static props merged after the shell-owned props. */\n props?: Record<string, unknown>;\n /** Evaluated whenever the shell enumerates the slot. */\n condition?: (props: PanelFrontendSlotProps<K>) => boolean;\n}\n\nexport interface FrontendSlotsService {\n /** Header action seat: pass a descriptor and the shell renders the button. */\n register(\n name: \"shell.header.actions\",\n action: PanelFrontendHeaderAction,\n options?: PanelFrontendSlotRegistration<\"shell.header.actions\">\n ): () => void;\n register<K extends PanelFrontendSlotName>(\n name: K,\n component: Component,\n options?: PanelFrontendSlotRegistration<K>\n ): () => void;\n entries<K extends PanelFrontendSlotName>(\n name: K,\n props: PanelFrontendSlotProps<K>\n ): readonly PanelFrontendSlotEntry<K>[];\n}\n\nexport interface FrontendMenusService {\n login(action: PanelFrontendLoginAction): () => void;\n readonly loginActions: readonly PanelFrontendLoginAction[];\n}\n\nexport interface FrontendActionsService {\n instance(action: PanelFrontendInstanceAction): () => void;\n schedule(action: PanelFrontendScheduleAction): () => void;\n terminal(action: PanelFrontendTerminalAction): () => void;\n readonly instances: readonly PanelFrontendInstanceAction[];\n readonly schedules: readonly PanelFrontendScheduleAction[];\n readonly terminals: readonly PanelFrontendTerminalAction[];\n /**\n * The registered terminal actions as the button descriptors both terminals\n * already render, so neither call site has to know how a registration looks.\n */\n terminalButtons(state: PanelFrontendTerminalActionContext): PanelFrontendTerminalButton[];\n}\n\nexport interface FrontendPluginsService {\n readonly loaded: readonly LoadedPanelFrontendPlugin[];\n readonly diagnostics: readonly PanelFrontendPluginDiagnostic[];\n load(id: string): Promise<LoadedPanelFrontendPlugin>;\n unload(id: string): Promise<boolean>;\n reload(id: string): Promise<LoadedPanelFrontendPlugin>;\n /** Re-reads the installed plugins and loads or unloads to match. */\n refresh(): Promise<readonly PanelFrontendPluginMetadata[]>;\n /** Throws only when an entry declared `frontendRequired` is not active. */\n audit(): void;\n}\n\nexport interface PanelFrontendPluginDiagnostic {\n id: string;\n state: PluginState;\n required: boolean;\n revision?: string;\n requiredServices: readonly string[];\n missingServices: readonly string[];\n error?: string;\n}\n\nexport type FrontendConnectionStatus =\n | \"connecting\"\n | \"connected\"\n | \"degraded\"\n | \"disconnected\";\n\nexport interface FrontendConnectionState {\n status: FrontendConnectionStatus;\n networkAvailable: boolean;\n generation: number;\n retryAttempt: number;\n lastError?: string;\n changedAt: number;\n}\n\nexport interface FrontendConnectionService {\n readonly state: Readonly<FrontendConnectionState>;\n /** Cancels the current retry delay and probes the panel immediately. */\n reconnect(): void;\n}\n\n/**\n * Desktop mode's application registry.\n *\n * Supplied by the console plugin even though Desktop mode is optional. An\n * application belongs to whichever plugin owns the page and is disposed with\n * that plugin rather than with Desktop. Without `plugins/desktop` nothing renders\n * the registry and `window` is absent.\n */\nexport interface FrontendDesktopService {\n /** Adds an application to the Desktop, removed when the calling plugin unloads. */\n app(desktopApp: PanelFrontendDesktopApp): () => void;\n readonly apps: readonly PanelFrontendDesktopApp[];\n view(view: PanelFrontendDesktopView): () => void;\n readonly views: readonly PanelFrontendDesktopView[];\n open(request: PanelFrontendDesktopWindowRequest): boolean;\n provideOpener(open: (request: PanelFrontendDesktopWindowRequest) => boolean): () => void;\n /** The window shell a Desktop-mode component is mounted inside. */\n readonly window: Component | undefined;\n /** Supplies that shell. Called by `plugins/desktop`. */\n provideWindow(component: Component): () => void;\n /** The shared confirmation window supplied by `plugins/desktop`. */\n readonly confirmation: Component | undefined;\n provideConfirmation(component: Component): () => void;\n}\n\n/**\n * The file manager. Provided by `plugins/file`.\n *\n * It publishes more than a page: the upload queue the settings page and the\n * create-instance form drive, the file editor the mod manager and the backup\n * plugin open, the dialogs the panel mounts on demand, and the filename helpers\n * the code editor and archive preview use. Every consumer resolves it with\n * `usePluginService` and degrades when the plugin is absent.\n */\nexport interface FrontendFileManagerService {\n readonly api: Record<string, unknown>;\n readonly useFileManager: (...args: any[]) => any;\n readonly getFileConfigAddr: (...args: any[]) => any;\n readonly uploadService: any;\n readonly UploadFiles: any;\n readonly getFileIcon: (fileName: string, type?: number) => string;\n readonly getFileExtName: (fileName: string) => string;\n readonly filterFileName: (fileName: string) => string;\n readonly isCompressFile: (fileName: string) => boolean;\n readonly FileEditor: Component;\n readonly ImageViewer: Component;\n readonly DesktopFileManager: Component;\n readonly DesktopFileEditor: Component;\n readonly DesktopImageViewer: Component;\n useUploadFileDialog(): Promise<string>;\n useDownloadFileDialog(): Promise<any>;\n useImageViewerDialog(\n instanceId: string,\n daemonId: string,\n fileName: string,\n frontDir: string\n ): Promise<any>;\n}\n\n/** The instance terminal and its stream client. Provided by `plugins/terminal`. */\nexport interface FrontendTerminalService {\n readonly api: Record<string, unknown>;\n readonly TerminalCore: Component;\n readonly TerminalTags: Component;\n readonly TerminalTopTags: Component;\n readonly useTerminal: (...args: any[]) => any;\n readonly useCommandHistory: (...args: any[]) => any;\n readonly encodeConsoleColor: (text: string) => string;\n}\n\n/** Minecraft mod and plugin APIs. Provided by `plugins/mod`. */\nexport interface FrontendModManagerService {\n readonly api: typeof import(\"../../../../plugins/mod-manager/panel/src/api\");\n}\n\n/** Java environment selector supplied by `plugins/instance`. */\nexport interface FrontendJavaService {\n readonly setupComponent: Component;\n}\n\n/** Application instance pages, APIs, hooks and dialogs. Provided by `plugins/instance`. */\nexport interface FrontendInstanceService {\n readonly api: Record<string, (...args: any[]) => any>;\n openConsole(instance: unknown, daemonId: string): boolean;\n readonly hooks: typeof import(\"../../../../plugins/instance/panel/src/hooks/useInstance\") &\n typeof import(\"../../../../plugins/instance/panel/src/hooks/useInstanceTag\") &\n typeof import(\"../../../../plugins/instance/panel/src/hooks/quickStartFlow\") & {\n useSchedule: typeof import(\"../../../../plugins/instance/panel/src/hooks/useSchedule\").useSchedule;\n useServerConfig: typeof import(\"../../../../plugins/instance/panel/src/hooks/useServerConfig\").useServerConfig;\n useStartCmdBuilder: typeof import(\"../../../../plugins/instance/panel/src/hooks/useGenerateStartCmd\").useStartCmdBuilder;\n };\n readonly components: {\n readonly CmdAssistantDialog: Component;\n readonly CreateInstanceForm: Component;\n readonly InstanceDetail: Component;\n readonly DeleteInstanceDialog: Component;\n readonly DockerCapabilityDialog: Component;\n readonly DockerDeviceDialog: Component;\n readonly DockerPortDialog: Component;\n readonly DockerVersionSelectDialog: Component;\n readonly NodeSelectDialog: Component;\n readonly SelectInstances: Component;\n readonly TagsDialog: Component;\n };\n}\n\n/** Accounts and sessions. Provided by `plugins/user`. */\nexport interface FrontendUserService {\n restoreSession(): Promise<void>;\n readonly api: UserPluginApi;\n readonly desktopLoginWindow: Component;\n readonly desktopUsers: Component;\n readonly desktopUserInfo: Component;\n readonly desktopStartMenuAvatar: Component;\n}\n\n/** The app market service supplied by an installed market plugin. */\nexport interface FrontendMarketService {\n readonly api: Record<string, unknown>;\n openMarketDialog(\n daemonId?: string,\n instanceId?: string,\n options?: { autoInstall?: boolean; onlyDockerTemplate?: boolean }\n ): Promise<unknown>;\n useMarketPackages(options?: Record<string, unknown>): unknown;\n}\n\n/** Node management. Provided by `plugins/node`. */\nexport interface FrontendNodeService {\n readonly api: NodePluginApi;\n useRemoteNode(): RemoteNodeHook;\n}\n\ndeclare module \"cordis\" {\n interface Events {\n \"plugins/loaded\"(): void | Promise<void>;\n }\n\n interface Context {\n startup: FrontendStartupService;\n // Services provided by the foundational frontend plugins.\n vue: FrontendVueService;\n console: FrontendConsoleService;\n // Provided first by the foundational `i18n` plugin.\n i18n: FrontendI18nService;\n routes: FrontendRoutesService;\n ui: FrontendUiService;\n slots: FrontendSlotsService;\n menus: FrontendMenusService;\n actions: FrontendActionsService;\n plugins: FrontendPluginsService;\n desktop: FrontendDesktopService;\n connection: FrontendConnectionService;\n\n // Provided by plugins. Read them with `usePluginService()` for graceful\n // degradation, or `inject` them from a plugin that cannot work without one.\n user: FrontendUserService;\n market: FrontendMarketService;\n node: FrontendNodeService;\n instance: FrontendInstanceService;\n mod: FrontendModManagerService;\n java: FrontendJavaService;\n file: FrontendFileManagerService;\n terminal: FrontendTerminalService;\n }\n}\n\n/** The context a frontend plugin's `apply()` receives. */\nexport type PanelFrontendPluginContext = Context;\n"],"names":["ctx","Context","serviceRevision","shallowRef","usePluginService","name"],"mappings":"8FAyBa,MAAAA,EAAM,IAAIC,EAQVC,EAAkBC,EAAW,CAAC,EAC3CH,EAAI,GAAG,mBAAoB,IAAM,CAC/BE,EAAgB,OAAS,CAC3B,CAAC,EAMM,SAASE,EAAoBC,EAA6B,CAC/D,OAAKH,EAAgB,MACdF,EAAI,IAAIK,CAAa,CAC9B"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{u as y}from"./useMountComponent-
|
|
2
|
-
//# sourceMappingURL=copy-
|
|
1
|
+
import{u as y}from"./useMountComponent-4043cb4c.js";import{u as U}from"./context-cc90576e.js";import{t as i}from"./i18n-e810b9fa.js";import{_ as L}from"./lodash-001e4f93.js";import{e as P,r as z,m as w}from"./useDefineApi-b726db1e.js";import{a1 as G,bz as I,aE as b,O as v,ba as m,$ as f,bJ as s,gz as K,gA as Y,Q as O,R as V,P as J,gC as h,gE as B,_ as X,bP as S,gH as Z,gI as Q,F as q,aK as W,bM as ee,gJ as te,gK as ae,gB as ne,gL as re,gD as oe,N as R,d7 as le,ac as A}from"./vue-6b52a630.js";import"./AppDialog.vue_vue_type_style_index_0_lang-e6e38e8b.js";import{d as H}from"./dayjs.min-25183c0a.js";import{M as ie}from"./vuetifyModal-8382b175.js";const se={key:0,class:"text-body-medium text-medium-emphasis mb-4"},ue=["innerHTML"],ce={class:"d-flex justify-end mb-5"},F=G({__name:"KvOptionsDialog",props:{title:{},keyTitle:{},valueTitle:{},data:{},subTitle:{},columns:{},textarea:{type:Boolean},destroyComponent:{type:Function},emitResult:{type:Function}},setup(e){const t=e,a=I(t.data instanceof Array?L.cloneDeep(t.data):[]),n=I(!0),r=I(),o=async()=>{n.value=!1,t.destroyComponent&&t.destroyComponent()},l=async()=>{var c;try{const p=await((c=r.value)==null?void 0:c.validate());if(!(p!=null&&p.valid))return}catch(p){return z(p)}t.emitResult&&t.emitResult(a.value),await o()},T=R(()=>t.columns?[...t.columns,{align:"center",key:"operation",dataIndex:"operation",title:i("TXT_CODE_fe731dfc")}]:[{align:"center",key:"k",dataIndex:"k",title:t.keyTitle},{align:"center",key:"v",dataIndex:"v",title:t.valueTitle},{align:"center",key:"operation",dataIndex:"operation",title:i("TXT_CODE_fe731dfc")}]),k=R(()=>T.value.map(c=>({title:c.title||"",key:String(c.dataIndex||c.key||""),align:c.align||"center",sortable:!1}))),u=c=>(c==null?void 0:c.raw)??c,D=c=>String(c.dataIndex||c.key||""),M=(c,p=0)=>{if(c==="add"){const g=T.value.filter(d=>d.dataIndex).map(d=>String(d.dataIndex)),C={};for(const d of g)d!=="operation"&&(C[d]="");a.value.push(C)}else a.value.splice(p,1)};return(c,p)=>(b(),v(s(oe),{modelValue:n.value,"onUpdate:modelValue":p[1]||(p[1]=g=>n.value=g),class:"app-dialog","max-width":"1300",persistent:""},{default:m(()=>[f(s(K),{title:t.title},{default:m(()=>[f(s(Y),{class:"dialog-overflow-container"},{default:m(()=>[t.subTitle?(b(),O("div",se,[V("span",{innerHTML:t.subTitle},null,8,ue)])):J("",!0),V("div",ce,[f(s(h),{variant:"tonal",onClick:p[0]||(p[0]=g=>M("add"))},{default:m(()=>[f(s(B),{start:"",icon:"mdi-plus-circle-outline"}),X(" "+S(s(i)("TXT_CODE_dfc17a0c")),1)]),_:1})]),f(s(Z),{ref_key:"formInstance",ref:r},{default:m(()=>[f(s(Q),{headers:k.value,items:a.value,"items-per-page":-1,"hide-default-footer":"",density:"comfortable"},{item:m(({item:g,index:C})=>[V("tr",null,[(b(!0),O(q,null,W(T.value,d=>(b(),O("td",{key:D(d),class:ee(`text-${d.align||"center"}`)},[D(d)==="operation"?(b(),v(s(h),{key:0,icon:"",variant:"text",color:"error",size:"small",onClick:_=>M("del",C)},{default:m(()=>[f(s(B),{icon:"mdi-minus-circle-outline"})]),_:1},8,["onClick"])):t.textarea?(b(),v(s(te),{key:1,"model-value":u(g)[D(d)],placeholder:d.placeholder,rows:"2","auto-grow":"","hide-details":"auto",rules:[_=>s(P)(_).then(()=>!0).catch(x=>x.message)],"onUpdate:modelValue":_=>u(g)[D(d)]=_},null,8,["model-value","placeholder","rules","onUpdate:modelValue"])):(b(),v(s(ae),{key:2,"model-value":u(g)[D(d)],placeholder:d.placeholder,"hide-details":"auto",rules:[_=>s(P)(_).then(()=>!0).catch(x=>x.message)],"onUpdate:modelValue":_=>u(g)[D(d)]=_},null,8,["model-value","placeholder","rules","onUpdate:modelValue"]))],2))),128))])]),_:1},8,["headers","items"])]),_:1},512)]),_:1}),f(s(ne),null,{default:m(()=>[f(s(re)),f(s(h),{variant:"text",onClick:o},{default:m(()=>[X(S(s(i)("TXT_CODE_a0451c97")),1)]),_:1}),f(s(h),{color:"primary",onClick:l},{default:m(()=>[X(S(s(i)("TXT_CODE_d507abff")),1)]),_:1})]),_:1})]),_:1},8,["title"])]),_:1},8,["modelValue"]))}});function E(){const e=U("instance");if(!e)throw new Error('Panel frontend plugin "instance" is not loaded.');return e.components}async function ke(e=[]){return y({data:e}).mount(E().SelectInstances)}async function xe(e=[]){return y({data:e}).mount(E().DockerPortDialog)}async function Ie(e=[]){return y({data:e,subTitle:i("TXT_CODE_6c232c9c"),title:i("TXT_CODE_820ebc92"),columns:[{align:"center",dataIndex:"host",title:i("TXT_CODE_681aaeb9")},{align:"center",dataIndex:"container",title:i("TXT_CODE_30258325")}],textarea:!0}).mount(F)}async function Oe(e=[]){return y({data:e,title:i("TXT_CODE_90a9d317"),columns:[{align:"center",dataIndex:"label",title:i("TXT_CODE_a42984e")},{align:"center",dataIndex:"value",title:i("TXT_CODE_115e8a25")}],textarea:!0}).mount(F)}async function Ve(e=[]){return y({data:e,title:i("TXT_CODE_g1c43s2h"),subTitle:i("TXT_CODE_MimBB1Ea"),columns:[{align:"center",dataIndex:"label",title:i("TXT_CODE_a42984e")},{align:"center",dataIndex:"value",title:i("TXT_CODE_115e8a25")}],textarea:!0}).mount(F)}async function Xe(e=[]){return y({data:e,title:i("TXT_CODE_bbbd4133"),subTitle:i("TXT_CODE_377319df"),textarea:!1}).mount(E().DockerCapabilityDialog)}async function Se(e=[]){return y({data:e,title:i("TXT_CODE_b3a60c78"),subTitle:i("TXT_CODE_b6e18b87"),textarea:!1}).mount(E().DockerDeviceDialog)}async function Ae(e,t,a,n){return await y({instanceId:e,daemonId:t,tagsTips:n,tags:a}).load(E().TagsDialog).openDialog()}function Ne(e=0){return e?H(e).format("YYYY-MM-DD HH:mm:ss"):""}function Fe(e){return e?e.valueOf():0}function Me(e=0){if(e)return H(e)}async function Pe(e){return new Promise(t=>setTimeout(t,e))}function we(e,t=""){const a=t.split("/");function n(r,o){if(!o)return null;const l=r.shift();return r.length!==0?n(r,o[l]):o[l]}return n(a,e)}function j(e,t="",a={}){for(const n in e){let r=null;t?r=`${t}/${n}`:r=`${n}`;const o=e[n];o===null||o===""?Object.defineProperty(a,r,{enumerable:!0,configurable:!0,get(){return e[n]??""},set(l){e[n]=l}}):o instanceof Array?typeof o[0]=="object"?j(o,r,a):Object.defineProperty(a,r,{enumerable:!0,configurable:!0,get(){return e[n]},set(l){e[n]=String(l).split(",")}}):typeof o=="object"?j(o,r,a):Object.defineProperty(a,r,{enumerable:!0,configurable:!0,get(){const l=e[n];return typeof l=="number"&&l>=Number.MAX_SAFE_INTEGER||l<=Number.MIN_SAFE_INTEGER?BigInt(l).toString():e[n]},set(l){if((typeof o=="number"&&o>=Number.MAX_SAFE_INTEGER||o<=Number.MIN_SAFE_INTEGER)&&(e[n]=BigInt(o).toString()),typeof e[n]=="number"&&!isNaN(Number(l)))return e[n]=Number(l);e[n]=l}})}return a}function Be(e){let t="";for(let a=0;a<e.length;a++)/([\u4E00-\u9FA5]|[\uFE30-\uFFA0])/g.test(e[a])?t+="\\u"+de(parseInt(e.charCodeAt(a).toString(16)).toString()):t+=e[a];return t}function de(e){return e!=null&&e!==""&&e!=="undefined"&&e.length==2?"00"+e:e||""}const N=e=>/\[([0-9a-fA-F:]+)\]/g.test(e),pe=e=>{let t=e.join(":"),a;const n=new Map;if(N(t)){a=t.match(/\[([0-9a-fA-F:]+)\]/g);for(let u=0;u<a.length;u++)t=t.replace(a[u],"IPv6_"+u),n.set("IPv6_"+u,a[u])}let r=N(e.join(":"))?t.split(":"):e,o=[],l=[];for(let u=0;u<r.length;u++)if($(r[0])&&r.length===3&&u<1||!$(r[0])&&r.length===3&&u<2||r.length===4&&u<2)o.push(r[u]);else{if(r.length===2)return{port1:r[0],port2:r[1]};l.push(r[u])}const T={port1:o.join(":"),port2:l.join(":")},k={port1:o.length===1?o[0]:o.join(":").replace(o[0],n.get(o[0])),port2:l.length===1?l[0]:l.join(":").replace(l[0],n.get(l[0]))};return N(e.join(":"))?k:T},Re=e=>e.map(a=>{const n=a.split("/"),r=n[0],o=n[1],{port1:l,port2:T}=pe(r.split(":"));return{host:l,container:T,protocol:o}}),$=e=>{if(e===null||e==="")return!1;for(let t=0;t<e.length;t++){const a=e[t];if(a<"0"||a>"9")return!1}return!0},je=e=>e==="0"?e:e.padStart(2,"0"),{copy:fe,copied:me,isSupported:ge}=le(),$e=async e=>{try{if(ge.value){if(await fe(String(e)),me.value)return w.success(i("TXT_CODE_b858d78a"))}else{const t=document.createElement("input");return t.setAttribute("value",String(e)),document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t),w.success(i("TXT_CODE_b858d78a"))}}catch(t){console.error(t),ie.warning({title:i("TXT_CODE_ca07c84c"),content:[A("span",i("TXT_CODE_2452016e")),A("br"),A("span",e)]})}};export{xe as a,Ie as b,Oe as c,Re as d,Ve as e,Xe as f,Se as g,Me as h,Fe as i,je as j,we as k,j as l,Be as m,Ae as o,Ne as p,Pe as s,$e as t,ke as u};
|
|
2
|
+
//# sourceMappingURL=copy-b106bb10.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-b106bb10.js","sources":["../../../../plugins/console/panel/src/components/fc/KvOptionsDialog.vue","../../../../plugins/console/panel/src/components/fc/index.ts","../../../../plugins/console/panel/src/tools/time.ts","../../../../plugins/console/panel/src/tools/common.ts","../../../../plugins/console/panel/src/tools/copy.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport { t } from \"@/lang/i18n\";\nimport type { MountComponent } from \"../../types\";\nimport _ from \"lodash\";\nimport { computed, ref } from \"vue\";\nimport { VBtn, VCard, VCardActions, VCardText, VDataTable, VDialog, VForm, VIcon, VSpacer, VTextarea, VTextField } from \"vuetify/components\";\nimport { emptyValueValidator, reportValidatorError } from \"../../tools/validator\";\n\ninterface KvColumn {\n align?: string;\n key?: string;\n dataIndex?: string;\n title?: string;\n placeholder?: string;\n}\n\ninterface Props extends MountComponent {\n title: string;\n keyTitle?: string;\n valueTitle?: string;\n data: any[];\n subTitle?: string;\n columns?: KvColumn[];\n textarea?: boolean;\n}\n\nconst props = defineProps<Props>();\nconst dataSource = ref<any[]>(props.data instanceof Array ? _.cloneDeep(props.data) : []);\n\nconst open = ref(true);\nconst formInstance = ref<any>();\n\nconst cancel = async () => {\n open.value = false;\n if (props.destroyComponent) props.destroyComponent();\n};\n\nconst submit = async () => {\n try {\n const result = await formInstance.value?.validate();\n if (!result?.valid) return;\n } catch (error: any) {\n return reportValidatorError(error);\n }\n if (props.emitResult) props.emitResult(dataSource.value);\n await cancel();\n};\n\nconst columns = computed<KvColumn[]>(() => {\n if (props.columns) {\n return [\n ...props.columns,\n {\n align: \"center\",\n key: \"operation\",\n dataIndex: \"operation\",\n title: t(\"TXT_CODE_fe731dfc\")\n }\n ];\n }\n return [\n {\n align: \"center\",\n key: \"k\",\n dataIndex: \"k\",\n title: props.keyTitle\n },\n {\n align: \"center\",\n key: \"v\",\n dataIndex: \"v\",\n title: props.valueTitle\n },\n {\n align: \"center\",\n key: \"operation\",\n dataIndex: \"operation\",\n title: t(\"TXT_CODE_fe731dfc\")\n }\n ];\n});\n\nconst tableHeaders = computed(() =>\n columns.value.map((column) => ({\n title: column.title || \"\",\n key: String(column.dataIndex || column.key || \"\"),\n align: (column.align || \"center\") as \"start\" | \"center\" | \"end\",\n sortable: false\n }))\n);\n\nconst getRecord = (item: any) => item?.raw ?? item;\nconst getColumnKey = (column: KvColumn) => String(column.dataIndex || column.key || \"\");\n\nconst operation = (type: \"add\" | \"del\", index = 0) => {\n if (type === \"add\") {\n const keys = columns.value.filter((v) => v.dataIndex).map((v) => String(v.dataIndex));\n const obj: any = {};\n for (const key of keys) {\n if (key === \"operation\") continue;\n obj[key] = \"\";\n }\n dataSource.value.push(obj);\n } else {\n dataSource.value.splice(index, 1);\n }\n};\n</script>\n\n<template>\n <VDialog v-model=\"open\" class=\"app-dialog\" max-width=\"1300\" persistent>\n <VCard :title=\"props.title\">\n <VCardText class=\"dialog-overflow-container\">\n <div v-if=\"props.subTitle\" class=\"text-body-medium text-medium-emphasis mb-4\">\n <!-- eslint-disable-next-line vue/no-v-html -->\n <span v-html=\"props.subTitle\"></span>\n </div>\n <div class=\"d-flex justify-end mb-5\">\n <VBtn variant=\"tonal\" @click=\"operation('add')\">\n <VIcon start icon=\"mdi-plus-circle-outline\" />\n {{ t(\"TXT_CODE_dfc17a0c\") }}\n </VBtn>\n </div>\n <VForm ref=\"formInstance\">\n <VDataTable :headers=\"tableHeaders\" :items=\"dataSource\" :items-per-page=\"-1\" hide-default-footer density=\"comfortable\">\n <template #item=\"{ item, index }\">\n <tr>\n <td v-for=\"column in columns\" :key=\"getColumnKey(column)\" :class=\"`text-${column.align || 'center'}`\">\n <VBtn v-if=\"getColumnKey(column) === 'operation'\" icon variant=\"text\" color=\"error\" size=\"small\" @click=\"operation('del', index)\">\n <VIcon icon=\"mdi-minus-circle-outline\" />\n </VBtn>\n <VTextarea\n v-else-if=\"props.textarea\"\n :model-value=\"getRecord(item)[getColumnKey(column)]\"\n :placeholder=\"column.placeholder\"\n rows=\"2\"\n auto-grow\n hide-details=\"auto\"\n :rules=\"[(value) => emptyValueValidator(value).then(() => true).catch((error) => error.message)]\"\n @update:model-value=\"(value) => (getRecord(item)[getColumnKey(column)] = value)\"\n />\n <VTextField\n v-else\n :model-value=\"getRecord(item)[getColumnKey(column)]\"\n :placeholder=\"column.placeholder\"\n hide-details=\"auto\"\n :rules=\"[(value) => emptyValueValidator(value).then(() => true).catch((error) => error.message)]\"\n @update:model-value=\"(value) => (getRecord(item)[getColumnKey(column)] = value)\"\n />\n </td>\n </tr>\n </template>\n </VDataTable>\n </VForm>\n </VCardText>\n <VCardActions>\n <VSpacer />\n <VBtn variant=\"text\" @click=\"cancel\">{{ t(\"TXT_CODE_a0451c97\") }}</VBtn>\n <VBtn color=\"primary\" @click=\"submit\">{{ t(\"TXT_CODE_d507abff\") }}</VBtn>\n </VCardActions>\n </VCard>\n </VDialog>\n</template>\n\n<style lang=\"scss\" scoped></style>\n","import { useMountComponent } from \"@/hooks/useMountComponent\";\nimport { usePluginService, type FrontendInstanceService } from \"@/plugin/context\";\nimport type { UserInstance } from \"@/types/user\";\n\nimport KvOptionsDialogVue from \"@/components/fc/KvOptionsDialog.vue\";\nimport { t } from \"@/lang/i18n\";\nimport TaskLoadingDialog from \"./TaskLoadingDialog.vue\";\n\n// The file manager's own dialogs — upload, download-from-URL and the image\n// viewer — moved to `plugins/file`, which owns the components they mount.\n\ninterface DockerConfigItem {\n host: string;\n container: string;\n}\ninterface PortConfigItem extends DockerConfigItem {\n protocol: string;\n}\n\ninterface DockerEnvItem {\n label: string;\n value: string;\n}\n\ninterface DockerLabelItem {\n label: string;\n value: string;\n}\n\ninterface DockerCapabilityItem {\n label: string;\n value: string;\n}\n\ninterface DockerDeviceItem {\n PathOnHost: string;\n PathInContainer: string;\n CgroupPermissions: string;\n}\n\nfunction instanceComponents() {\n const instance = usePluginService<FrontendInstanceService>(\"instance\");\n if (!instance) throw new Error('Panel frontend plugin \"instance\" is not loaded.');\n return instance.components;\n}\n\nexport async function useSelectInstances(data: UserInstance[] = []) {\n return useMountComponent({ data }).mount<UserInstance[]>(instanceComponents().SelectInstances);\n}\n\nexport async function useCmdAssistantDialog() {\n return await useMountComponent().mount<string>(instanceComponents().CmdAssistantDialog);\n}\n\nexport async function usePortEditDialog(data: PortConfigItem[] = []) {\n return useMountComponent({ data }).mount<PortConfigItem[]>(instanceComponents().DockerPortDialog);\n}\n\nexport async function useVolumeEditDialog(data: DockerConfigItem[] = []) {\n return useMountComponent({\n data,\n subTitle: t(\"TXT_CODE_6c232c9c\"),\n title: t(\"TXT_CODE_820ebc92\"),\n columns: [\n {\n align: \"center\",\n dataIndex: \"host\",\n title: t(\"TXT_CODE_681aaeb9\")\n },\n {\n align: \"center\",\n dataIndex: \"container\",\n title: t(\"TXT_CODE_30258325\")\n }\n ],\n textarea: true\n }).mount<DockerConfigItem[]>(KvOptionsDialogVue);\n}\n\nexport async function useDockerEnvEditDialog(data: DockerEnvItem[] = []) {\n return useMountComponent({\n data,\n title: t(\"TXT_CODE_90a9d317\"),\n columns: [\n {\n align: \"center\",\n dataIndex: \"label\",\n title: t(\"TXT_CODE_a42984e\")\n },\n {\n align: \"center\",\n dataIndex: \"value\",\n title: t(\"TXT_CODE_115e8a25\")\n }\n ],\n textarea: true\n }).mount<DockerEnvItem[]>(KvOptionsDialogVue);\n}\n\nexport async function useDockerLabelEditDialog(data: DockerLabelItem[] = []) {\n return useMountComponent({\n data,\n title: t(\"TXT_CODE_g1c43s2h\"),\n subTitle: t(\"TXT_CODE_MimBB1Ea\"),\n columns: [\n {\n align: \"center\",\n dataIndex: \"label\",\n title: t(\"TXT_CODE_a42984e\")\n },\n {\n align: \"center\",\n dataIndex: \"value\",\n title: t(\"TXT_CODE_115e8a25\")\n }\n ],\n textarea: true\n }).mount<DockerLabelItem[]>(KvOptionsDialogVue);\n}\n\nexport async function useDockerCapabilityEditDialog(data: DockerCapabilityItem[] = []) {\n return useMountComponent({\n data,\n title: t(\"TXT_CODE_bbbd4133\"),\n subTitle: t(\"TXT_CODE_377319df\"),\n textarea: false\n }).mount<DockerCapabilityItem[]>(instanceComponents().DockerCapabilityDialog);\n}\n\nexport async function useDockerDeviceEditDialog(data: DockerDeviceItem[] = []) {\n return useMountComponent({\n data,\n title: t(\"TXT_CODE_b3a60c78\"),\n subTitle: t(\"TXT_CODE_b6e18b87\"),\n textarea: false\n }).mount<DockerDeviceItem[]>(instanceComponents().DockerDeviceDialog);\n}\n\nexport async function openLoadingDialog(title: string, text: string, subTitle?: string) {\n const component = useMountComponent({\n title,\n text,\n subTitle\n }).load<InstanceType<typeof TaskLoadingDialog>>(TaskLoadingDialog);\n return component;\n}\n\nexport async function openInstanceTagsEditor(\n instanceId: string,\n daemonId: string,\n tags: string[],\n tagsTips?: string[]\n) {\n return await useMountComponent({\n instanceId,\n daemonId,\n tagsTips,\n tags\n })\n .load<any>(instanceComponents().TagsDialog)\n .openDialog();\n}\n\nexport async function useDeleteInstanceDialog(instanceId: string, daemonId: string) {\n return await useMountComponent({ instanceId, daemonId }).mount<boolean>(\n instanceComponents().DeleteInstanceDialog\n );\n}\n\nexport async function openNodeSelectDialog(targetPlatforms?: string[]) {\n const dialog = useMountComponent({ targetPlatforms }).load<any>(\n instanceComponents().NodeSelectDialog\n );\n return dialog!.openDialog();\n}\n\nexport async function openDockerVersionSelectDialog() {\n const dialog = useMountComponent().load<any>(instanceComponents().DockerVersionSelectDialog);\n return dialog!.openDialog();\n}\n","import dayjs from \"dayjs\";\nimport type { Dayjs } from \"dayjs\";\n\nexport function parseTimestamp(st = 0) {\n if (!st) return \"\";\n return dayjs(st).format(\"YYYY-MM-DD HH:mm:ss\");\n}\n\nexport function dayjsToTimestamp(dayjs?: Dayjs) {\n if (!dayjs) return 0;\n return dayjs.valueOf();\n}\n\nexport function timestampToDayjs(st = 0) {\n if (!st) return;\n return dayjs(st);\n}\n","import type { JsonData } from \"@/types\";\nimport { h } from \"vue\";\n\nexport async function sleep(t: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, t));\n}\n\nexport async function loadingIconFc(fontSize = 24) {\n const indicator = h(\"i\", {\n class: \"mdi mdi-loading mdi-spin\",\n style: { fontSize: `${fontSize}px` }\n });\n return indicator;\n}\n\ninterface Description {\n [key: string]: any;\n}\n\nexport function getDescriptionByTitle(description: Description, title: string = \"\") {\n const arr: string[] = title.split(\"/\");\n\n function _exec(keys: string[], _description: Description) {\n if (!_description) return null;\n const currentTitle: string | undefined = keys.shift();\n if (keys.length !== 0) {\n return _exec(keys, _description[currentTitle!]);\n } else {\n return _description[currentTitle!];\n }\n }\n\n return _exec(arr, description);\n}\n\nexport function jsonToMap(json: JsonData, topTitle = \"\", map = {}) {\n for (const key in json) {\n let title = null;\n if (topTitle) {\n title = `${topTitle}/${key}`;\n } else {\n title = `${key}`;\n }\n const value = json[key];\n if (value === null || value === \"\") {\n Object.defineProperty(map, title, {\n enumerable: true,\n configurable: true,\n get() {\n return json[key] ?? \"\";\n },\n set(v) {\n json[key] = v;\n }\n });\n } else if (value instanceof Array) {\n if (typeof value[0] === \"object\") {\n jsonToMap(value, title, map);\n } else {\n Object.defineProperty(map, title, {\n enumerable: true,\n configurable: true,\n get() {\n return json[key];\n },\n set(v) {\n json[key] = String(v).split(\",\");\n }\n });\n }\n } else if (typeof value === \"object\") {\n jsonToMap(value, title, map);\n } else {\n Object.defineProperty(map, title, {\n enumerable: true,\n configurable: true,\n get() {\n const value = json[key];\n if (\n (typeof value === \"number\" && value >= Number.MAX_SAFE_INTEGER) ||\n value <= Number.MIN_SAFE_INTEGER\n ) {\n return BigInt(value).toString();\n }\n return json[key];\n },\n set(v) {\n if (\n (typeof value === \"number\" && value >= Number.MAX_SAFE_INTEGER) ||\n value <= Number.MIN_SAFE_INTEGER\n ) {\n json[key] = BigInt(value).toString();\n }\n const preValue = json[key];\n if (typeof preValue === \"number\" && !isNaN(Number(v))) return (json[key] = Number(v));\n json[key] = v;\n }\n });\n }\n }\n return map;\n}\n\nexport function toUnicode(str: string) {\n let value = \"\";\n for (let i = 0; i < str.length; i++) {\n if (/([\\u4E00-\\u9FA5]|[\\uFE30-\\uFFA0])/g.test(str[i])) {\n value += \"\\\\u\" + leftZero4(parseInt(str.charCodeAt(i).toString(16)).toString());\n } else {\n value += str[i];\n }\n }\n return value;\n}\n\nfunction leftZero4(str: string) {\n if (str != null && str !== \"\" && str !== \"undefined\") {\n if (str.length == 2) {\n return \"00\" + str;\n }\n }\n return str || \"\";\n}\n\nconst isIPv6 = (str: string) => {\n return /\\[([0-9a-fA-F:]+)\\]/g.test(str);\n};\n\nexport const dockerPortsParse = (ports: string[]) => {\n let joinArr = ports.join(\":\");\n let tempAddr: RegExpMatchArray | null;\n const ipMaps = new Map();\n\n if (isIPv6(joinArr)) {\n tempAddr = joinArr.match(/\\[([0-9a-fA-F:]+)\\]/g);\n for (let i = 0; i < tempAddr!.length; i++) {\n joinArr = joinArr.replace(tempAddr![i], \"IPv6_\" + i);\n ipMaps.set(\"IPv6_\" + i, tempAddr![i]);\n }\n }\n\n let p = isIPv6(ports.join(\":\")) ? joinArr.split(\":\") : ports;\n\n let p1 = [],\n p2 = [];\n\n for (let i = 0; i < p.length; i++) {\n if (\n (isInt(p[0]) && p.length === 3 && i < 1) ||\n (!isInt(p[0]) && p.length === 3 && i < 2) ||\n (p.length === 4 && i < 2)\n ) {\n p1.push(p[i]);\n } else if (p.length === 2) {\n return { port1: p[0], port2: p[1] };\n } else {\n p2.push(p[i]);\n }\n }\n\n const v4 = { port1: p1.join(\":\"), port2: p2.join(\":\") };\n\n const v6 = {\n port1: p1.length === 1 ? p1[0] : p1.join(\":\").replace(p1[0], ipMaps.get(p1[0])),\n port2: p2.length === 1 ? p2[0] : p2.join(\":\").replace(p2[0], ipMaps.get(p2[0]))\n };\n\n return isIPv6(ports.join(\":\")) ? v6 : v4;\n};\n\nexport const dockerPortsArray = (ports: string[]) => {\n const portArray = ports.map((iterator) => {\n const pad = iterator.split(\"/\");\n const ports = pad[0];\n const protocol = pad[1];\n const { port1, port2 } = dockerPortsParse(ports.split(\":\"));\n return {\n host: port1,\n container: port2,\n protocol\n };\n });\n return portArray;\n};\n\nexport const isInt = (x: any) => {\n if (x === null || x === \"\") {\n return false;\n }\n for (let i = 0; i < x.length; i++) {\n const char = x[i];\n if (char < \"0\" || char > \"9\") {\n return false;\n }\n }\n return true;\n};\n\nexport const padZero = (num: string) => (num === \"0\" ? num : num.padStart(2, \"0\"));\n\nexport const getUsageColor = (num: number, normalColor: string = \"var(--color-primary)\"): string =>\n num >= 80 ? \"var(--color-danger)\" : num >= 60 ? \"var(--color-warning)\" : normalColor;\n","import { t } from \"@/lang/i18n\";\nimport { useClipboard } from \"@vueuse/core\";\nimport { message } from \"@/tools/vuetifyToast\";\nimport { Modal } from \"@/tools/vuetifyModal\";\nimport { h } from \"vue\";\n\nconst { copy, copied, isSupported } = useClipboard();\n\nexport const toCopy = async (sth: string | number) => {\n try {\n if (!isSupported.value) {\n const input = document.createElement(\"input\");\n input.setAttribute(\"value\", String(sth));\n document.body.appendChild(input);\n input.select();\n document.execCommand(\"copy\");\n document.body.removeChild(input);\n return message.success(t(\"TXT_CODE_b858d78a\"));\n } else {\n await copy(String(sth));\n if (copied.value) return message.success(t(\"TXT_CODE_b858d78a\"));\n }\n } catch (err: any) {\n console.error(err);\n Modal.warning({\n title: t(\"TXT_CODE_ca07c84c\"),\n content: [h(\"span\", t(\"TXT_CODE_2452016e\")), h(\"br\"), h(\"span\", sth)]\n });\n }\n};\n"],"names":["props","__props","dataSource","ref","_","open","formInstance","cancel","submit","result","_a","error","reportValidatorError","columns","computed","t","tableHeaders","column","getRecord","item","getColumnKey","operation","type","index","keys","v","obj","key","_createBlock","_unref","VDialog","$event","_createVNode","VCard","VCardText","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_3","VBtn","VIcon","_createTextVNode","VForm","VDataTable","_withCtx","_Fragment","_renderList","_normalizeClass","VTextarea","value","emptyValueValidator","VTextField","VCardActions","VSpacer","instanceComponents","instance","usePluginService","useSelectInstances","data","useMountComponent","usePortEditDialog","useVolumeEditDialog","KvOptionsDialogVue","useDockerEnvEditDialog","useDockerLabelEditDialog","useDockerCapabilityEditDialog","useDockerDeviceEditDialog","openInstanceTagsEditor","instanceId","daemonId","tags","tagsTips","parseTimestamp","st","dayjs","dayjsToTimestamp","timestampToDayjs","sleep","resolve","getDescriptionByTitle","description","title","arr","_exec","_description","currentTitle","jsonToMap","json","topTitle","map","toUnicode","str","i","leftZero4","isIPv6","dockerPortsParse","ports","joinArr","tempAddr","ipMaps","p","p1","p2","isInt","v4","v6","dockerPortsArray","iterator","pad","protocol","port1","port2","x","char","padZero","num","copy","copied","isSupported","useClipboard","toCopy","sth","message","input","err","Modal","h"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{co as a,cp as t,cq as r,eY as u,cr as o,eZ as n,cs as i,ct as c,cu as d,cv as f,cw as l,cx as g,cy as m,e_ as p,e$ as y,f0 as S,cz as b,cr as h,f1 as v,cA as D,f2 as T,f3 as F,f2 as P,f4 as R,f5 as A,cB as k,f6 as w,f7 as M,f8 as C,f9 as O,cC as W,fa as E,fb as L,cD as I,cE as B,cF as x,fc as U,fd as V,fe as H,cG as N,cH as j,cI as z,cJ as K,ff as G,f1 as Q,cK as q,fg as J,fh as Z,cL as X,fi as Y,cM as _,fj as $,fk as ee,fl as se,fm as ae,fn as te,fo as re,fp as ue,fq as oe,fr as ne,fs as ie,ft as ce,fu as de,cN as fe,fv as le,fw as ge,fx as me,fy as pe,fz as ye,fA as Se,fB as be,cO as he,cP as ve,cQ as De,cR as Te,cS as Fe,cT as Pe,cU as Re,fC as Ae,fD as ke,fE as we,fF as Me,f9 as Ce,fG as Oe,fH as We,fI as Ee,fJ as Le,eZ as Ie,fd as Be,fK as xe,fL as Ue,fM as Ve,fN as He,fO as Ne,fP as je,cV as ze,fQ as Ke,fR as Ge,cW as Qe,fS as qe,fL as Je,fT as Ze,fU as Xe,fV as Ye,fW as _e,fX as $e,fY as es,fZ as ss,f_ as as,f$ as ts,g0 as rs,g1 as us,cX as os,g2 as ns,cY as is,cZ as cs,g3 as ds,g4 as fs,g5 as ls,g6 as gs,g7 as ms,g8 as ps,g9 as ys,ga as Ss,gb as bs,gc as hs,gd as vs,ge as Ds,c_ as Ts,c$ as Fs,d0 as Ps,d1 as Rs,d2 as As,d3 as ks,d4 as ws,d5 as Ms,d6 as Cs,d7 as Os,d8 as Ws,d9 as Es,da as Ls,gf as Is,db as Bs,dc as xs,dd as Us,de as Vs,gg as Hs,fd as Ns,gh as js,df as zs,dg as Ks,dh as Gs,di as Qs,dj as qs,dk as Js,dl as Zs,dm as Xs,dn as Ys,dp as _s,dq as $s,dr as ea,ds as sa,dt as aa,du as ta,dv as ra,dw as ua,dx as oa,dy as na,dz as ia,dA as ca,dB as da,dC as fa,dD as la,dE as ga,dF as ma,dG as pa,dH as ya,dI as Sa,dJ as ba,dK as ha,dL as va,gi as Da,gj as Ta,dM as Fa,gk as Pa,dN as Ra,dO as Aa,dP as ka,dQ as wa,dR as Ma,dS as Ca,dT as Oa,dU as Wa,dV as Ea,dW as La,dX as Ia,dY as Ba,dZ as xa,d_ as Ua,d$ as Va,e0 as Ha,e1 as Na,e2 as ja,e3 as za,e4 as Ka,e5 as Ga,e6 as Qa,e7 as qa,e8 as Ja,e9 as Za,ea as Xa,eb as Ya,ec as _a,ed as $a,ee as et,ef as st,eg as at,eh as tt,ei as rt,ej as ut,ek as ot,el as nt,em as it,en as ct,eo as dt,ep as ft,eq as lt,er as gt,es as mt,et as pt,eu as yt,ev as St,ew as bt,ex as ht,ey as vt,ez as Dt,eA as Tt,eB as Ft,eC as Pt,eD as Rt,fL as At,gl as kt,eE as wt,eF as Mt,gm as Ct,gn as Ot,eG as Wt,eH as Et,eI as Lt,go as It,gp as Bt,gq as xt,eJ as Ut,eK as Vt,eL as Ht,eM as Nt,eN as jt,eO as zt,eP as Kt,eQ as Gt,eR as Qt,eS as qt,eT as Jt,eU as Zt,eV as Xt,eW as Yt,eX as _t,gr as $t,gs as er,fe as sr,gt as ar,fm as tr,gu as rr,gv as ur,fD as or,fT as nr,gw as ir,gx as cr,gy as dr}from"./vue-
|
|
2
|
-
//# sourceMappingURL=core-
|
|
1
|
+
import{co as a,cp as t,cq as r,eY as u,cr as o,eZ as n,cs as i,ct as c,cu as d,cv as f,cw as l,cx as g,cy as m,e_ as p,e$ as y,f0 as S,cz as b,cr as h,f1 as v,cA as D,f2 as T,f3 as F,f2 as P,f4 as R,f5 as A,cB as k,f6 as w,f7 as M,f8 as C,f9 as O,cC as W,fa as E,fb as L,cD as I,cE as B,cF as x,fc as U,fd as V,fe as H,cG as N,cH as j,cI as z,cJ as K,ff as G,f1 as Q,cK as q,fg as J,fh as Z,cL as X,fi as Y,cM as _,fj as $,fk as ee,fl as se,fm as ae,fn as te,fo as re,fp as ue,fq as oe,fr as ne,fs as ie,ft as ce,fu as de,cN as fe,fv as le,fw as ge,fx as me,fy as pe,fz as ye,fA as Se,fB as be,cO as he,cP as ve,cQ as De,cR as Te,cS as Fe,cT as Pe,cU as Re,fC as Ae,fD as ke,fE as we,fF as Me,f9 as Ce,fG as Oe,fH as We,fI as Ee,fJ as Le,eZ as Ie,fd as Be,fK as xe,fL as Ue,fM as Ve,fN as He,fO as Ne,fP as je,cV as ze,fQ as Ke,fR as Ge,cW as Qe,fS as qe,fL as Je,fT as Ze,fU as Xe,fV as Ye,fW as _e,fX as $e,fY as es,fZ as ss,f_ as as,f$ as ts,g0 as rs,g1 as us,cX as os,g2 as ns,cY as is,cZ as cs,g3 as ds,g4 as fs,g5 as ls,g6 as gs,g7 as ms,g8 as ps,g9 as ys,ga as Ss,gb as bs,gc as hs,gd as vs,ge as Ds,c_ as Ts,c$ as Fs,d0 as Ps,d1 as Rs,d2 as As,d3 as ks,d4 as ws,d5 as Ms,d6 as Cs,d7 as Os,d8 as Ws,d9 as Es,da as Ls,gf as Is,db as Bs,dc as xs,dd as Us,de as Vs,gg as Hs,fd as Ns,gh as js,df as zs,dg as Ks,dh as Gs,di as Qs,dj as qs,dk as Js,dl as Zs,dm as Xs,dn as Ys,dp as _s,dq as $s,dr as ea,ds as sa,dt as aa,du as ta,dv as ra,dw as ua,dx as oa,dy as na,dz as ia,dA as ca,dB as da,dC as fa,dD as la,dE as ga,dF as ma,dG as pa,dH as ya,dI as Sa,dJ as ba,dK as ha,dL as va,gi as Da,gj as Ta,dM as Fa,gk as Pa,dN as Ra,dO as Aa,dP as ka,dQ as wa,dR as Ma,dS as Ca,dT as Oa,dU as Wa,dV as Ea,dW as La,dX as Ia,dY as Ba,dZ as xa,d_ as Ua,d$ as Va,e0 as Ha,e1 as Na,e2 as ja,e3 as za,e4 as Ka,e5 as Ga,e6 as Qa,e7 as qa,e8 as Ja,e9 as Za,ea as Xa,eb as Ya,ec as _a,ed as $a,ee as et,ef as st,eg as at,eh as tt,ei as rt,ej as ut,ek as ot,el as nt,em as it,en as ct,eo as dt,ep as ft,eq as lt,er as gt,es as mt,et as pt,eu as yt,ev as St,ew as bt,ex as ht,ey as vt,ez as Dt,eA as Tt,eB as Ft,eC as Pt,eD as Rt,fL as At,gl as kt,eE as wt,eF as Mt,gm as Ct,gn as Ot,eG as Wt,eH as Et,eI as Lt,go as It,gp as Bt,gq as xt,eJ as Ut,eK as Vt,eL as Ht,eM as Nt,eN as jt,eO as zt,eP as Kt,eQ as Gt,eR as Qt,eS as qt,eT as Jt,eU as Zt,eV as Xt,eW as Yt,eX as _t,gr as $t,gs as er,fe as sr,gt as ar,fm as tr,gu as rr,gv as ur,fD as or,fT as nr,gw as ir,gx as cr,gy as dr}from"./vue-6b52a630.js";export{a as DefaultMagicKeysAliasMap,t as StorageSerializers,r as TransitionPresets,u as assert,o as asyncComputed,n as autoResetRef,i as breakpointsAntDesign,c as breakpointsBootstrapV5,d as breakpointsMasterCss,f as breakpointsQuasar,l as breakpointsSematic,g as breakpointsTailwind,m as breakpointsVuetify,p as bypassFilter,y as camelize,S as clamp,b as cloneFnJSON,h as computedAsync,v as computedEager,D as computedInject,T as computedWithControl,F as containsProp,P as controlledComputed,R as controlledRef,A as createEventHook,k as createFetch,w as createFilterWrapper,M as createGlobalState,C as createInjectionState,O as createReactiveFn,W as createReusableTemplate,E as createSharedComposable,L as createSingletonPromise,I as createTemplatePromise,B as createUnrefFn,x as customStorageEventName,U as debounceFilter,V as debouncedRef,H as debouncedWatch,N as defaultDocument,j as defaultLocation,z as defaultNavigator,K as defaultWindow,G as directiveHooks,Q as eagerComputed,q as executeTransition,J as extendRef,Z as formatDate,X as formatTimeAgo,Y as get,_ as getSSRHandler,$ as hasOwn,ee as hyphenate,se as identity,ae as ignorableWatch,te as increaseWithUnit,re as invoke,ue as isClient,oe as isDef,ne as isDefined,ie as isIOS,ce as isObject,de as makeDestructurable,fe as mapGamepadToXbox360Controller,le as noop,ge as normalizeDate,me as notNullish,pe as now,ye as objectEntries,Se as objectOmit,be as objectPick,he as onClickOutside,ve as onKeyDown,De as onKeyPressed,Te as onKeyStroke,Fe as onKeyUp,Pe as onLongPress,Re as onStartTyping,Ae as pausableFilter,ke as pausableWatch,we as promiseTimeout,Me as rand,Ce as reactify,Oe as reactifyObject,We as reactiveComputed,Ee as reactiveOmit,Le as reactivePick,Ie as refAutoReset,Be as refDebounced,xe as refDefault,Ue as refThrottled,Ve as refWithControl,He as resolveRef,Ne as resolveUnref,je as set,ze as setSSRHandler,Ke as syncRef,Ge as syncRefs,Qe as templateRef,qe as throttleFilter,Je as throttledRef,Ze as throttledWatch,Xe as timestamp,Ye as toReactive,_e as toRef,$e as toRefs,es as toValue,ss as tryOnBeforeMount,as as tryOnBeforeUnmount,ts as tryOnMounted,rs as tryOnScopeDispose,us as tryOnUnmounted,os as unrefElement,ns as until,is as useActiveElement,cs as useAnimate,ds as useArrayDifference,fs as useArrayEvery,ls as useArrayFilter,gs as useArrayFind,ms as useArrayFindIndex,ps as useArrayFindLast,ys as useArrayIncludes,Ss as useArrayJoin,bs as useArrayMap,hs as useArrayReduce,vs as useArraySome,Ds as useArrayUnique,Ts as useAsyncQueue,Fs as useAsyncState,Ps as useBase64,Rs as useBattery,As as useBluetooth,ks as useBreakpoints,ws as useBroadcastChannel,Ms as useBrowserLocation,Cs as useCached,Os as useClipboard,Ws as useCloned,Es as useColorMode,Ls as useConfirmDialog,Is as useCounter,Bs as useCssVar,xs as useCurrentElement,Us as useCycleList,Vs as useDark,Hs as useDateFormat,Ns as useDebounce,js as useDebounceFn,zs as useDebouncedRefHistory,Ks as useDeviceMotion,Gs as useDeviceOrientation,Qs as useDevicePixelRatio,qs as useDevicesList,Js as useDisplayMedia,Zs as useDocumentVisibility,Xs as useDraggable,Ys as useDropZone,_s as useElementBounding,$s as useElementByPoint,ea as useElementHover,sa as useElementSize,aa as useElementVisibility,ta as useEventBus,ra as useEventListener,ua as useEventSource,oa as useEyeDropper,na as useFavicon,ia as useFetch,ca as useFileDialog,da as useFileSystemAccess,fa as useFocus,la as useFocusWithin,ga as useFps,ma as useFullscreen,pa as useGamepad,ya as useGeolocation,Sa as useIdle,ba as useImage,ha as useInfiniteScroll,va as useIntersectionObserver,Da as useInterval,Ta as useIntervalFn,Fa as useKeyModifier,Pa as useLastChanged,Ra as useLocalStorage,Aa as useMagicKeys,ka as useManualRefHistory,wa as useMediaControls,Ma as useMediaQuery,Ca as useMemoize,Oa as useMemory,Wa as useMounted,Ea as useMouse,La as useMouseInElement,Ia as useMousePressed,Ba as useMutationObserver,xa as useNavigatorLanguage,Ua as useNetwork,Va as useNow,Ha as useObjectUrl,Na as useOffsetPagination,ja as useOnline,za as usePageLeave,Ka as useParallax,Ga as useParentElement,Qa as usePerformanceObserver,qa as usePermission,Ja as usePointer,Za as usePointerLock,Xa as usePointerSwipe,Ya as usePreferredColorScheme,_a as usePreferredContrast,$a as usePreferredDark,et as usePreferredLanguages,st as usePreferredReducedMotion,at as usePrevious,tt as useRafFn,rt as useRefHistory,ut as useResizeObserver,ot as useScreenOrientation,nt as useScreenSafeArea,it as useScriptTag,ct as useScroll,dt as useScrollLock,ft as useSessionStorage,lt as useShare,gt as useSorted,mt as useSpeechRecognition,pt as useSpeechSynthesis,yt as useStepper,St as useStorage,bt as useStorageAsync,ht as useStyleTag,vt as useSupported,Dt as useSwipe,Tt as useTemplateRefsList,Ft as useTextDirection,Pt as useTextSelection,Rt as useTextareaAutosize,At as useThrottle,kt as useThrottleFn,wt as useThrottledRefHistory,Mt as useTimeAgo,Ct as useTimeout,Ot as useTimeoutFn,Wt as useTimeoutPoll,Et as useTimestamp,Lt as useTitle,It as useToNumber,Bt as useToString,xt as useToggle,Ut as useTransition,Vt as useUrlSearchParams,Ht as useUserMedia,Nt as useVModel,jt as useVModels,zt as useVibrate,Kt as useVirtualList,Gt as useWakeLock,Qt as useWebNotification,qt as useWebSocket,Jt as useWebWorker,Zt as useWebWorkerFn,Xt as useWindowFocus,Yt as useWindowScroll,_t as useWindowSize,$t as watchArray,er as watchAtMost,sr as watchDebounced,ar as watchDeep,tr as watchIgnorable,rr as watchImmediate,ur as watchOnce,or as watchPausable,nr as watchThrottled,ir as watchTriggerable,cr as watchWithFilter,dr as whenever};
|
|
2
|
+
//# sourceMappingURL=core-d3bfdede.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core-d3bfdede.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{n as e}from"./useDefineApi-
|
|
2
|
-
//# sourceMappingURL=desktopNotice-
|
|
1
|
+
import{n as e}from"./useDefineApi-b726db1e.js";function i(s,n="info"){const t=typeof s=="string"?{message:s}:{message:s.message,description:s.description};!t.message&&!t.description||e[n]({...t,placement:"top"})}function a(s,n=""){const t=typeof s=="string"?s:s instanceof Error?s.message:String((s==null?void 0:s.message)??n);i(t||n,"error")}export{a,i as n};
|
|
2
|
+
//# sourceMappingURL=desktopNotice-5ca3448c.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"desktopNotice-5ca3448c.js","sources":["../../../../plugins/console/panel/src/tools/desktopNotice.ts"],"sourcesContent":["import { notification } from \"@/tools/vuetifyToast\";\n\nexport type DesktopNoticeType = \"success\" | \"error\" | \"warning\" | \"info\";\n\nexport interface DesktopNoticeInput {\n message?: string;\n description?: string;\n}\n\nexport function notifyDesktop(\n input: string | DesktopNoticeInput,\n type: DesktopNoticeType = \"info\"\n) {\n const options = typeof input === \"string\"\n ? { message: input }\n : { message: input.message, description: input.description };\n if (!options.message && !options.description) return;\n notification[type]({ ...options, placement: \"top\" });\n}\n\nexport function notifyDesktopError(error: unknown, fallback = \"\") {\n const text = typeof error === \"string\"\n ? error\n : error instanceof Error\n ? error.message\n : String((error as { message?: unknown } | null)?.message ?? fallback);\n notifyDesktop(text || fallback, \"error\");\n}\n"],"names":["notifyDesktop","input","type","options","notification","notifyDesktopError","error","fallback","text"],"mappings":"+CASgB,SAAAA,EACdC,EACAC,EAA0B,OAC1B,CACA,MAAMC,EAAU,OAAOF,GAAU,SAC7B,CAAE,QAASA,CAAA,EACX,CAAE,QAASA,EAAM,QAAS,YAAaA,EAAM,WAAY,EACzD,CAACE,EAAQ,SAAW,CAACA,EAAQ,aACjCC,EAAaF,CAAI,EAAE,CAAE,GAAGC,EAAS,UAAW,MAAO,CACrD,CAEgB,SAAAE,EAAmBC,EAAgBC,EAAW,GAAI,CAChE,MAAMC,EAAO,OAAOF,GAAU,SAC1BA,EACAA,aAAiB,MACfA,EAAM,QACN,QAAQA,GAAA,YAAAA,EAAwC,UAAWC,CAAQ,EAC3DP,EAAAQ,GAAQD,EAAU,OAAO,CACzC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom-ff483262.js","sources":["
|
|
1
|
+
{"version":3,"file":"dom-ff483262.js","sources":["../../../../plugins/console/panel/src/tools/dom.ts"],"sourcesContent":["export function findParentWithClass(element: HTMLElement, className: string): HTMLElement | null {\n if (element.classList.contains(className)) {\n return element;\n }\n let parentElement = element.parentElement;\n\n while (parentElement !== null) {\n if (parentElement.classList.contains(className)) {\n return parentElement;\n }\n parentElement = parentElement.parentElement;\n }\n\n return null;\n}\n\nexport function closeAppLoading() {\n window.closeLoadingContainer();\n}\n\nexport function setLoadingTitle(title: string) {\n window.setLoadingTitle(title);\n}\n\nexport function setAppLoadingError(error: string) {\n window.setAppLoadingError(error);\n}\n"],"names":["closeAppLoading","setLoadingTitle","title","setAppLoadingError","error"],"mappings":"AAgBO,SAASA,GAAkB,CAChC,OAAO,sBAAsB,CAC/B,CAEO,SAASC,EAAgBC,EAAe,CAC7C,OAAO,gBAAgBA,CAAK,CAC9B,CAEO,SAASC,EAAmBC,EAAe,CAChD,OAAO,mBAAmBA,CAAK,CACjC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{c as e}from"./context-
|
|
2
|
-
//# sourceMappingURL=i18n-
|
|
1
|
+
import{c as e}from"./context-cc90576e.js";const i="LANGUAGE";function o(n){return n?n.trim().replace(/-/g,"_").toLowerCase():"en_us"}function t(){const n=e.get("i18n");if(!n)throw new Error('Panel frontend plugin "i18n" is not loaded.');return n}function u(){return t().instance}function c(n,r=!0){t().setLanguage(n,r)}function g(){return t().getCurrentLang()}function f(){return t().isCN()}function a(...n){return t().translate(...n)}const L=a;export{i as L,o as a,u as b,g,f as i,c as s,L as t};
|
|
2
|
+
//# sourceMappingURL=i18n-e810b9fa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n-e810b9fa.js","sources":["../../../../plugins/i18n/panel/src/lang/i18n.ts"],"sourcesContent":["import type { I18n } from \"vue-i18n\";\nimport { ctx } from \"@/plugin/context\";\nimport type { FrontendI18nService, PanelLanguageOption } from \"@/plugin\";\n\nexport const LANGUAGE_KEY = \"LANGUAGE\";\n\nexport function toStandardLang(language?: string) {\n if (!language) return \"en_us\";\n return language.trim().replace(/-/g, \"_\").toLowerCase();\n}\n\nfunction service(): FrontendI18nService {\n const i18n = ctx.get(\"i18n\");\n if (!i18n) throw new Error('Panel frontend plugin \"i18n\" is not loaded.');\n return i18n;\n}\n\nexport function getI18nInstance(): I18n {\n return service().instance;\n}\n\nexport function getSupportedLanguageOptions(): readonly PanelLanguageOption[] {\n return service().supportedLanguages;\n}\n\nexport function getSupportLanguages(): string[] {\n return service().getSupportLanguages();\n}\n\nexport function searchSupportLanguage(language: string): string {\n return service().searchSupportLanguage(language);\n}\n\nexport function setLanguage(language: string, reload = true): void {\n service().setLanguage(language, reload);\n}\n\nexport function getCurrentLang(): string {\n return service().getCurrentLang();\n}\n\nexport function isCN(): boolean {\n return service().isCN();\n}\n\nexport function isEN(): boolean {\n return service().isEN();\n}\n\nexport function $t(...args: any[]): string {\n return service().translate(...args);\n}\n\nexport const t = $t;\n"],"names":["LANGUAGE_KEY","toStandardLang","language","service","i18n","ctx","getI18nInstance","setLanguage","reload","getCurrentLang","isCN","$t","args","t"],"mappings":"0CAIO,MAAMA,EAAe,WAErB,SAASC,EAAeC,EAAmB,CAChD,OAAKA,EACEA,EAAS,OAAO,QAAQ,KAAM,GAAG,EAAE,cADpB,OAExB,CAEA,SAASC,GAA+B,CAChC,MAAAC,EAAOC,EAAI,IAAI,MAAM,EAC3B,GAAI,CAACD,EAAY,MAAA,IAAI,MAAM,6CAA6C,EACjE,OAAAA,CACT,CAEO,SAASE,GAAwB,CACtC,OAAOH,EAAU,EAAA,QACnB,CAcgB,SAAAI,EAAYL,EAAkBM,EAAS,GAAY,CACzDL,IAAE,YAAYD,EAAUM,CAAM,CACxC,CAEO,SAASC,GAAyB,CAChC,OAAAN,EAAA,EAAU,gBACnB,CAEO,SAASO,GAAgB,CACvB,OAAAP,EAAA,EAAU,MACnB,CAMO,SAASQ,KAAMC,EAAqB,CACzC,OAAOT,EAAQ,EAAE,UAAU,GAAGS,CAAI,CACpC,CAEO,MAAMC,EAAIF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{c}from"./context-cc90576e.js";import{_ as K}from"./preload-helper-a4192956.js";import{c as X,v as M,r as Y}from"./plugin_contract-691cd37a.js";import{bA as N}from"./vue-6b52a630.js";import"./_elements-sdk_cordis-e3bebc89.js";import"./_elements-sdk_cosmokit-e4842f5c.js";import"./htmlparser2-bcb8f9db.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))n(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&n(o)}).observe(document,{childList:!0,subtree:!0});function r(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function n(i){if(i.ep)return;i.ep=!0;const s=r(i);fetch(i.href,s)}})();function Z(e){const t=new Set,r=[],n=new WeakSet,i=new WeakSet,s=o=>{if(i.has(o))return;i.add(o);const g=o.reset;o.reset=function(){return this.disposables=this.disposables.map(u=>{if(n.has(u))return u;const h=(...l)=>{let a;try{a=u(...l)}catch(d){throw r.push(d),d}if(a&&typeof a.then=="function"){const d=Promise.resolve(a).catch(p=>{r.push(p)}).finally(()=>t.delete(d));t.add(d)}return a};for(const l of Object.getOwnPropertySymbols(u))Object.defineProperty(h,l,Object.getOwnPropertyDescriptor(u,l));return n.add(h),h}),g.call(this)}};return e.on("internal/runtime",s),e.on("internal/fork",s),async()=>{do await e.events.flush(),await Promise.all([...t]);while(t.size);if(r.length){const o=r.splice(0);throw new Error(`Plugin cleanup failed: ${o.map(String).join("; ")}`)}}}const J={runtime:"startup",i18n:"i18n",console:"console"},w=new Set(Object.keys(J)),O=X(),b=Z(c),m=N([]),P=new Map;function G(e,t){return(Number(e.metadata.priority)||0)-(Number(t.metadata.priority)||0)||e.metadata.id.localeCompare(t.metadata.id)}function ee(e){return Array.isArray(e.inject)?[...new Set(e.inject)]:e.inject?Object.entries(e.inject).filter(([,t])=>t==null?void 0:t.required).map(([t])=>t):[]}function te(e){if(!e||e.error||e.runtime.error)return"failed";switch(e.status){case 0:return"pending";case 1:return"loading";case 2:return"active";case 3:case 4:return"failed";default:return"pending"}}function re(e){e.missingServices=e.requiredServices.filter(t=>!c.get(t)),e.state=e.restartRequired||e.reloadRequired?"restart-required":e.error?"failed":te(e.fork)}function H(e){var r,n;const t=e.error||((r=e.fork)==null?void 0:r.error)||((n=e.fork)==null?void 0:n.runtime.error);if(t!=null)return t instanceof Error?t:new Error(String(t))}function S(){for(const e of m)re(e)}c.on("internal/status",e=>{m.find(r=>r.fork===e)&&S()});function V(e){const t=typeof e.id=="string"?e.id.trim():"";return t?{...e,id:t}:null}function ne(e,t){for(const r of[e,e==null?void 0:e.default])if(!(typeof r!="object"||r===null)&&typeof r.apply=="function")return r;c.logger("plugin").warn(`Panel frontend plugin "${t}" must export an apply() function.`)}async function ae(e){const t=[];try{await Promise.all((e.styles||[]).map(r=>new Promise((n,i)=>{const s=document.createElement("link");s.rel="stylesheet",s.href=r,s.dataset.panelPlugin=e.metadata.id,s.addEventListener("load",()=>n(),{once:!0}),s.addEventListener("error",()=>i(new Error(`Failed to load panel plugin stylesheet: ${r}`)),{once:!0}),document.head.appendChild(s),t.push(s)})))}catch(r){throw t.forEach(n=>n.remove()),r}return()=>t.forEach(r=>r.remove())}function oe(e,t){document.querySelectorAll(`style[data-panel-plugin=${JSON.stringify(e.metadata.id)}]`).forEach(r=>{t!=null&&t.has(r)||r.remove()});for(const r of e.styles||[]){const n=new URL(r,document.baseURI).href;document.querySelectorAll("link[rel='stylesheet']").forEach(i=>{try{!(t!=null&&t.has(i))&&new URL(i.href,document.baseURI).href===n&&i.remove()}catch{}})}}async function ie(){const e=new URL("plugins/manifest.json",document.baseURI),t=await fetch(e.href,{cache:"no-store"});if(!t.ok){if(t.status===404)return[];throw new Error(`Failed to load panel plugin manifest: HTTP ${t.status}`)}const r=await t.json(),n=Array.isArray(r)?r:r==null?void 0:r.data;if(!Array.isArray(n))throw new Error("Invalid panel plugin manifest.");const i=o=>new URL(o,e).href,s=[];for(const o of n){if(!o||typeof o!="object"||Array.isArray(o))continue;const g=V(o.metadata||o),u=typeof o.entry=="string"?o.entry:"";if(!g||g.enabled===!1||!u)continue;const h=i(u);s.push({metadata:g,directory:typeof o.directory=="string"?o.directory:g.id,assetDirectory:typeof o.assetDirectory=="string"?o.assetDirectory:g.id,entry:h,revision:typeof o.revision=="string"?o.revision:String(g.version||""),styles:Array.isArray(o.styles)?o.styles.filter(l=>typeof l=="string").map(i):[],load:async l=>{const a=new URL(h);return l&&a.searchParams.set("panel_plugin_reload",l),K(()=>import(a.href),[],import.meta.url)}})}return s}async function _(){const e=await ie(),t=new Map;for(const r of e){const n=V(r.metadata);!n||n.enabled===!1||t.has(n.id)||t.set(n.id,{...r,metadata:n})}return[...t.values()].sort(G)}function j(e){return Y(e,{id:t=>t.metadata.id,dependencies:t=>t.metadata.frontendInject,compare:G})}function se(e){const t=[];for(const r of j(e).ordered){try{M(r.metadata.elements)}catch{continue}if(r.metadata.restartRequired||!r.entry)continue;const n=document.createElement("link");n.rel="modulepreload",n.href=r.entry,n.crossOrigin="anonymous",document.head.appendChild(n),t.push(n);for(const i of r.styles||[]){const s=document.createElement("link");s.rel="preload",s.setAttribute("as","style"),s.href=i,document.head.appendChild(s),t.push(s)}}return()=>t.forEach(r=>r.remove())}async function I(e,t){let r;try{if(M(e.metadata.elements),e.metadata.restartRequired)throw new Error("The plugin backend requires a restart before this version can load.");const[n,i]=await Promise.allSettled([ae(e),Promise.resolve().then(()=>e.load(t))]);if(n.status==="rejected")throw n.reason;if(r=n.value,i.status==="rejected")throw i.reason;const s=ne(i.value,e.metadata.id);if(!s)throw new Error(`Panel frontend plugin has no apply() export: ${e.metadata.id}`);return{module:s,removeStyles:r}}catch(n){return r==null||r(),{error:n instanceof Error?n:new Error(String(n))}}}function L(e,t){const r=m.find(i=>i.metadata.id===e.metadata.id);if(r)return r.error=t,r.state="failed",S(),r;const n=N({source:e,metadata:e.metadata,directory:e.directory,revision:e.revision,state:"failed",requiredServices:[],missingServices:[],error:t});return m.push(n),S(),n}async function R(e,t,r,n){var g,u,h;const i=m.find(l=>l.metadata.id===e.metadata.id);if(i)return i;const s=(e.metadata.frontendInject||[]).filter(l=>{var a;return((a=m.find(d=>d.metadata.id===l))==null?void 0:a.state)!=="active"});if(s.length)return n&&"module"in n&&((g=n.removeStyles)==null||g.call(n)),L(e,new Error(`Frontend plugin dependencies are not active: ${s.join(", ")}`));const o=N({source:e,metadata:e.metadata,directory:e.directory,revision:e.revision,state:"loading",requiredServices:[],missingServices:[]});m.push(o),S();try{const l=n??await I(e,t);if("error"in l)throw l.error;o.removeStyles=l.removeStyles;const{module:a}=l;o.requiredServices=ee(a);{let d,p;if(o.fork=c.plugin({...a,name:e.metadata.id,apply:(...v)=>{try{return d=a.apply(...v)}catch(E){throw p=E,E}}},r===void 0?e.metadata.config:r),p)throw p;await d,c.logger("plugin").info(`Panel frontend plugin loaded: ${e.metadata.id}`)}}catch(l){o.error=l instanceof Error?l:new Error(String(l)),(u=o.fork)==null||u.dispose(),o.fork=void 0,(h=o.removeStyles)==null||h.call(o),c.logger("plugin").error(`Panel frontend plugin failed to load: ${e.metadata.id}`,l)}return S(),o}function de(e){const t=c.get("vue"),r=c.get("routes");return!t||!r?!1:t.router.currentRoute.value.matched.some(n=>r.ownerOf(n.path)===e.metadata.id)}async function q(e,t=!1,r){var o,g;if(w.has(e)&&!t)throw new Error(`The essential frontend plugin "${e}" cannot be unloaded.`);const n=m.find(u=>u.metadata.id===e);if(!n)return!1;n.state="unloading",S();const i=c.get("vue");!t&&i&&de(n)&&await i.router.replace("/404"),(o=n.fork)==null||o.dispose();try{await b()}catch(u){throw n.error=u instanceof Error?u:new Error(String(u)),u}(g=n.removeStyles)==null||g.call(n),oe(n.source,r);const s=m.indexOf(n);return s>=0&&m.splice(s,1),S(),c.logger("plugin").info(`Panel frontend plugin unloaded: ${e}`),!0}async function le(e){let t=P.get(e);if(t||(await k(),t=P.get(e)),!t)throw new Error(`Panel frontend plugin not found: ${e}`);return R(t)}async function ce(e){if(w.has(e))return await k(void 0,!0),m.find(r=>r.metadata.id===e);await q(e);{const r=await _();P.clear(),r.forEach(n=>P.set(n.metadata.id,n))}const t=P.get(e);if(!t)throw new Error(`Panel frontend plugin not found: ${e}`);return R(t,t.revision||String(t.metadata.version||"reload"))}async function k(e,t=!1){var u,h,l;e??(e=await _());const r=new Map(e.map(a=>[a.metadata.id,a]));P.clear(),r.forEach((a,d)=>P.set(d,a));const n=(a,d)=>a.revision!==d.source.revision||JSON.stringify(a.metadata)!==JSON.stringify(d.metadata);if(t||e.some(a=>{const d=m.find(p=>p.metadata.id===a.metadata.id);return d&&w.has(a.metadata.id)&&!a.metadata.restartRequired&&(n(a,d)||H(d))})){const a=j(e);for(const f of w){const y=r.get(f);if(!y||a.issues.has(f)||y.metadata.restartRequired)throw new Error(`Panel frontend foundation is unavailable for reload: ${f}`)}const d=new Set(document.querySelectorAll("style, link[rel='stylesheet']")),p=[...[...w].map(f=>r.get(f)),...a.ordered.filter(f=>!w.has(f.metadata.id))],v=await Promise.all(p.map(f=>I(f))),E=v.find((f,y)=>"error"in f&&w.has(p[y].metadata.id));if(E&&"error"in E){for(const f of v)"module"in f&&((u=f.removeStyles)==null||u.call(f));throw E.error}const W=new Set([...document.querySelectorAll("style, link[rel='stylesheet']")].filter(f=>!d.has(f))),D=(h=c.get("vue"))==null?void 0:h.router.currentRoute.value.fullPath,Q=c.lifecycle.isActive;c.lifecycle.isActive=!1;try{for(const y of[...m].reverse())await q(y.metadata.id,!0,W);for(const[y,$]of p.entries())await R($,void 0,void 0,v[y]),await b();for(const[y,$]of a.issues){const C=r.get(y);C&&L(C,new Error($.message))}A(),await c.parallel("plugins/loaded");const f=(l=c.get("vue"))==null?void 0:l.router;return D&&f&&await f.replace(D),await b(),S(),e.map(y=>y.metadata)}finally{Q&&await c.start()}}for(const a of[...m].reverse())w.has(a.metadata.id)||r.has(a.metadata.id)||await q(a.metadata.id);const s=j(e);for(const[a,d]of s.issues){const p=r.get(a);if(!p)continue;m.find(E=>E.metadata.id===a)&&!w.has(a)&&await q(a),L(p,new Error(d.message))}const o=[];for(const a of s.ordered){const d=m.find(v=>v.metadata.id===a.metadata.id);d&&(d.restartRequired=!!a.metadata.restartRequired);const p=d&&(n(a,d)||!!a.metadata.restartRequired!=!!d.source.metadata.restartRequired);if(d&&(p||a.metadata.restartRequired)){if(w.has(a.metadata.id)||a.metadata.restartRequired){d.restartRequired=!!a.metadata.restartRequired,d.reloadRequired=!!(p&&w.has(a.metadata.id));continue}await q(a.metadata.id)}m.some(v=>v.metadata.id===a.metadata.id)||o.push(a)}const g=await Promise.all(o.map(a=>I(a)));for(const[a,d]of o.entries())await R(d,void 0,void 0,g[a]);return await b(),S(),e.map(a=>a.metadata)}async function ue(){const e=await _();P.clear(),e.forEach(r=>P.set(r.metadata.id,r));const t=se(e);try{for(const r of w){const n=P.get(r);if(!n)throw new Error(`Panel frontend foundation plugin not found: ${r}`);const i=await R(n);if(i.error)throw i.error;if(!i.fork||!c.get(J[r]))throw new Error(`Panel frontend foundation plugin failed to initialize: ${r}`)}await k(e),window.dispatchEvent(new CustomEvent("elementspanel:plugins-changed"))}finally{t()}}function T(){return m}function U(){return m.map(e=>{const t=H(e);return{id:e.metadata.id,state:e.state,required:!!e.metadata.frontendRequired,revision:e.revision,requiredServices:[...e.requiredServices],missingServices:[...e.missingServices],...t?{error:t.message}:{}}})}function A(){S();const e=U().filter(t=>t.required&&t.state!=="active");if(e.length)throw new Error(`Required frontend plugins are not active: ${e.map(t=>`${t.id} (${t.state}${t.error?`: ${t.error}`:""})`).join(", ")}`)}const x=e=>O(()=>q(e)),z=e=>O(()=>le(e)),B=e=>O(()=>ce(e)),F=()=>O(async()=>{const e=await k();return window.dispatchEvent(new CustomEvent("elementspanel:plugins-changed")),e});function fe(){if(typeof EventSource>"u")return()=>{};const e=new EventSource(new URL("plugins/events",document.baseURI).href);let t="",r=!1,n;const i=()=>{r||F().catch(s=>{c.logger("plugin").error("Failed to synchronize plugins",s),n=setTimeout(i,2e3)})};return e.onmessage=s=>{let o;try{o=JSON.parse(s.data).revision}catch{return}typeof o!="string"||o===t||r||(t=o,n&&clearTimeout(n),i())},()=>{r=!0,n&&clearTimeout(n),e.close()}}async function me(){c.provide("plugins",void 0,!0),c.set("plugins",{get loaded(){return T()},get diagnostics(){return U()},load:z,unload:x,reload:B,refresh:F,audit:A}),await ue(),A(),window.ElementsPanelPlugins={load:z,unload:x,reload:B,refresh:F,loaded:T,diagnostics:U,audit:A},await c.parallel("plugins/loaded"),await c.start(),c.effect(fe)}me().catch(async e=>{var r;console.error("Plugin startup failed:",e);const t=c.get("startup");if(t)t.showError(e);else{const n=window;(r=n.setAppLoadingError)==null||r.call(n,e instanceof Error?e.message:String(e))}await c.stop()});
|
|
2
|
+
//# sourceMappingURL=index-1da88aed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"mappings":"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","names":["trackPluginDisposal","ctx","pending","failures","tracked","scopes","observe","scope","reset","dispose","wrapper","args","result","error","task","key","errors","FOUNDATION_SERVICES","ESSENTIAL_PLUGIN_IDS","change","createPluginQueue","settle","plugins","shallowReactive","sources","compareSources","a","b","requiredServices","module","value","name","scopeState","refreshPluginState","plugin","pluginError","_a","_b","notifyPluginDiagnostics","candidate","normalizeMetadata","id","toModule","loadStyles","source","links","href","resolve","reject","link","removePluginStyles","preserve","style","normalizedHref","fetchProductionSources","manifestUrl","response","body","manifest","toUrl","item","metadata","entry","entryUrl","cacheKey","url","__vitePreload","discoverSources","discovered","unique","resolveSourceGraph","resolvePluginDependencyOrder","preloadPluginAssets","validatePluginCompatibility","preparePlugin","removeStyles","styles","recordGraphFailure","existing","install","configOverride","prepared","unavailableDependencies","resources","applied","thrown","_c","isCurrentRoute","vue","routes","record","unloadPluginInternal","replacing","preserveStyles","index","loadPluginInternal","refreshPluginsInternal","reloadPluginInternal","forceFoundations","next","changedSource","current","graph","previousStyles","ordered","failedFoundation","element","location","started","issue","auditFrontendPlugins","router","changed","bootstrapPanelFrontendPlugins","removePreloads","getLoadedPlugins","getPluginDiagnostics","unloadPlugin","loadPlugin","reloadPlugin","refreshPlugins","watchPluginChanges","events","revision","stopped","retry","synchronize","event","setupPanelFrontendPlugins","startup","host"],"sources":["../../../common/src/plugin_lifecycle.ts","../../src/plugin/loader.ts","../../src/plugin/install.ts","../../src/main.ts"],"sourcesContent":["/** Cordis 3 starts async disposers without awaiting them. Track them per host. */\nexport function trackPluginDisposal(ctx: any) {\n const pending = new Set<Promise<unknown>>();\n const failures: unknown[] = [];\n const tracked = new WeakSet<Function>();\n const scopes = new WeakSet<object>();\n const observe = (scope: any) => {\n if (scopes.has(scope)) return;\n scopes.add(scope);\n const reset = scope.reset;\n scope.reset = function () {\n this.disposables = this.disposables.map((dispose: Function) => {\n if (tracked.has(dispose)) return dispose;\n const wrapper = (...args: unknown[]) => {\n let result: unknown;\n try {\n result = dispose(...args);\n } catch (error) {\n failures.push(error);\n throw error;\n }\n if (result && typeof (result as Promise<unknown>).then === \"function\") {\n const task = Promise.resolve(result)\n .catch((error) => {\n failures.push(error);\n })\n .finally(() => pending.delete(task));\n pending.add(task);\n }\n return result;\n };\n // Cordis marks persistent disposers with a symbol; preserve its semantics.\n for (const key of Object.getOwnPropertySymbols(dispose))\n Object.defineProperty(wrapper, key, Object.getOwnPropertyDescriptor(dispose, key)!);\n tracked.add(wrapper);\n return wrapper;\n });\n return reset.call(this);\n };\n };\n ctx.on(\"internal/runtime\", observe);\n ctx.on(\"internal/fork\", observe);\n return async () => {\n do {\n await ctx.events.flush();\n await Promise.all([...pending]);\n } while (pending.size);\n if (failures.length) {\n const errors = failures.splice(0);\n throw new Error(`Plugin cleanup failed: ${errors.map(String).join(\"; \")}`);\n }\n };\n}\n","import {\n createPluginQueue,\n resolvePluginDependencyOrder,\n type PluginState,\n validatePluginCompatibility\n} from \"../../../common/src/plugin_contract\";\nimport { trackPluginDisposal } from \"../../../common/src/plugin_lifecycle\";\nimport { shallowReactive } from \"vue\";\nimport type { EffectScope, ForkScope } from \"cordis\";\nimport {\n ctx,\n type PanelFrontendPluginContext,\n type PanelFrontendPluginDiagnostic\n} from \"./context\";\nimport { panelPluginModules } from \"virtual:panel-plugins\";\n\nconst FOUNDATION_SERVICES: Record<string, string> = {\n runtime: \"startup\",\n i18n: \"i18n\",\n console: \"console\"\n};\nconst ESSENTIAL_PLUGIN_IDS = new Set(Object.keys(FOUNDATION_SERVICES));\nconst change = createPluginQueue();\nconst settle = trackPluginDisposal(ctx);\n\n/**\n * Fetches plugin code and hands it to cordis.\n *\n * Discovery is unchanged: in development the Vite plugin supplies a virtual\n * module of static imports; in production the browser fetches\n * `plugins/manifest.json` and imports each entry by URL. What that feeds is now\n * `ctx.plugin()`, and unloading is `fork.dispose()` — every route, card, menu,\n * action and translation the plugin registered is an effect of its scope.\n */\n\nexport interface PanelFrontendPluginMetadata {\n id: string;\n version?: string;\n description?: string;\n enabled?: boolean;\n priority?: number;\n frontend?: string;\n ui?: string;\n frontendInject?: string[];\n frontendImmediate?: boolean;\n frontendRequired?: boolean;\n config?: unknown;\n restartRequired?: boolean;\n [key: string]: unknown;\n}\n\n/** A frontend plugin module, as its entry exports it. */\nexport interface PanelFrontendPluginModule {\n inject?: string[] | Record<string, { required: boolean }>;\n apply(ctx: PanelFrontendPluginContext, config?: unknown): void | Promise<void>;\n}\n\ninterface PluginSource {\n metadata: PanelFrontendPluginMetadata;\n directory: string;\n assetDirectory: string;\n entry?: string;\n revision?: string;\n styles?: string[];\n load: (cacheKey?: string) => Promise<Record<string, unknown>>;\n}\n\ntype PreparedPlugin =\n | { module: PanelFrontendPluginModule; removeStyles?: () => void }\n | { error: Error };\n\nexport interface LoadedPanelFrontendPlugin {\n metadata: PanelFrontendPluginMetadata;\n directory: string;\n state: PluginState;\n requiredServices: readonly string[];\n missingServices: readonly string[];\n revision?: string;\n fork?: ForkScope;\n error?: Error;\n restartRequired?: boolean;\n reloadRequired?: boolean;\n}\n\ninterface InternalPlugin extends LoadedPanelFrontendPlugin {\n source: PluginSource;\n /** Only the stylesheet links, which are not cordis effects. */\n removeStyles?: () => void;\n}\n\nconst plugins = shallowReactive<InternalPlugin[]>([]);\nconst sources = new Map<string, PluginSource>();\n\nfunction compareSources(a: PluginSource, b: PluginSource) {\n return (\n (Number(a.metadata.priority) || 0) - (Number(b.metadata.priority) || 0) ||\n a.metadata.id.localeCompare(b.metadata.id)\n );\n}\n\nfunction requiredServices(module: PanelFrontendPluginModule) {\n if (Array.isArray(module.inject)) return [...new Set(module.inject)];\n if (!module.inject) return [];\n return Object.entries(module.inject)\n .filter(([, value]) => value?.required)\n .map(([name]) => name);\n}\n\nfunction scopeState(scope?: ForkScope): PluginState {\n if (!scope) return \"failed\";\n if (scope.error || scope.runtime.error) return \"failed\";\n switch (scope.status) {\n case 0: // ScopeStatus.PENDING\n return \"pending\";\n case 1: // ScopeStatus.LOADING\n return \"loading\";\n case 2: // ScopeStatus.ACTIVE\n return \"active\";\n case 3: // ScopeStatus.FAILED\n case 4: // ScopeStatus.DISPOSED\n return \"failed\";\n default:\n return \"pending\";\n }\n}\n\nfunction refreshPluginState(plugin: InternalPlugin) {\n plugin.missingServices = plugin.requiredServices.filter((name) => !ctx.get(name as never));\n plugin.state =\n plugin.restartRequired || plugin.reloadRequired\n ? \"restart-required\"\n : plugin.error\n ? \"failed\"\n : scopeState(plugin.fork);\n}\n\nfunction pluginError(plugin: InternalPlugin): Error | undefined {\n const error = plugin.error || plugin.fork?.error || plugin.fork?.runtime.error;\n if (error === undefined || error === null) return undefined;\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction notifyPluginDiagnostics() {\n for (const plugin of plugins) refreshPluginState(plugin);\n}\n\nctx.on(\"internal/status\", (scope: EffectScope) => {\n const plugin = plugins.find((candidate) => candidate.fork === scope);\n if (plugin) notifyPluginDiagnostics();\n});\n\nfunction normalizeMetadata(value: Record<string, unknown>): PanelFrontendPluginMetadata | null {\n const id = typeof value.id === \"string\" ? value.id.trim() : \"\";\n if (!id) return null;\n return { ...value, id } as PanelFrontendPluginMetadata;\n}\n\n/**\n * The plugin object a module exports, whether as named exports or as `default`.\n *\n * Only an object counts: every function has `Function.prototype.apply`, so a\n * module whose default export is a function would otherwise be mistaken for a\n * plugin and then called with the context as `this`.\n */\nfunction toModule(value: any, id: string): PanelFrontendPluginModule | undefined {\n for (const candidate of [value, value?.default]) {\n if (typeof candidate !== \"object\" || candidate === null) continue;\n if (typeof candidate.apply === \"function\") return candidate;\n }\n ctx.logger(\"plugin\").warn(`Panel frontend plugin \"${id}\" must export an apply() function.`);\n return undefined;\n}\n\nasync function loadStyles(source: PluginSource) {\n const links: HTMLLinkElement[] = [];\n try {\n await Promise.all(\n (source.styles || []).map(\n (href) =>\n new Promise<void>((resolve, reject) => {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = href;\n link.dataset.panelPlugin = source.metadata.id;\n link.addEventListener(\"load\", () => resolve(), { once: true });\n link.addEventListener(\n \"error\",\n () => reject(new Error(`Failed to load panel plugin stylesheet: ${href}`)),\n { once: true }\n );\n document.head.appendChild(link);\n links.push(link);\n })\n )\n );\n } catch (error) {\n links.forEach((link) => link.remove());\n throw error;\n }\n return () => links.forEach((link) => link.remove());\n}\n\n/**\n * Removes stylesheets the plugin injected itself, which the core cannot track:\n * `<style>` elements it tagged, and any `<link>` matching one of its hrefs.\n */\nfunction removePluginStyles(source: PluginSource, preserve?: Set<Element>) {\n document\n .querySelectorAll<HTMLStyleElement>(\n `style[data-panel-plugin=${JSON.stringify(source.metadata.id)}]`\n )\n .forEach((style) => {\n if (!preserve?.has(style)) style.remove();\n });\n for (const href of source.styles || []) {\n const normalizedHref = new URL(href, document.baseURI).href;\n document.querySelectorAll<HTMLLinkElement>(\"link[rel='stylesheet']\").forEach((link) => {\n try {\n if (!preserve?.has(link) && new URL(link.href, document.baseURI).href === normalizedHref)\n link.remove();\n } catch {\n // Ignore malformed third-party stylesheet URLs.\n }\n });\n }\n}\n\nasync function fetchProductionSources(): Promise<PluginSource[]> {\n const manifestUrl = new URL(\"plugins/manifest.json\", document.baseURI);\n const response = await fetch(manifestUrl.href, { cache: \"no-store\" });\n if (!response.ok) {\n if (response.status === 404) return [];\n throw new Error(`Failed to load panel plugin manifest: HTTP ${response.status}`);\n }\n const body = await response.json();\n // Older panel builds may still pass the manifest through the standard API\n // envelope. Accept both the raw array and `{ data: [...] }` forms.\n const manifest = Array.isArray(body) ? body : body?.data;\n if (!Array.isArray(manifest)) throw new Error(\"Invalid panel plugin manifest.\");\n\n const toUrl = (value: string) => new URL(value, manifestUrl).href;\n const result: PluginSource[] = [];\n for (const item of manifest) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) continue;\n const metadata = normalizeMetadata((item as any).metadata || item);\n const entry = typeof (item as any).entry === \"string\" ? (item as any).entry : \"\";\n if (!metadata || metadata.enabled === false || !entry) continue;\n const entryUrl = toUrl(entry);\n result.push({\n metadata,\n directory:\n typeof (item as any).directory === \"string\" ? (item as any).directory : metadata.id,\n assetDirectory:\n typeof (item as any).assetDirectory === \"string\"\n ? (item as any).assetDirectory\n : metadata.id,\n entry: entryUrl,\n revision: typeof item.revision === \"string\" ? item.revision : String(metadata.version || \"\"),\n styles: Array.isArray((item as any).styles)\n ? (item as any).styles\n .filter((style: unknown): style is string => typeof style === \"string\")\n .map(toUrl)\n : [],\n load: async (cacheKey) => {\n const url = new URL(entryUrl);\n if (cacheKey) url.searchParams.set(\"panel_plugin_reload\", cacheKey);\n return import(/* @vite-ignore */ url.href) as Promise<Record<string, unknown>>;\n }\n });\n }\n return result;\n}\n\nasync function discoverSources() {\n const discovered = import.meta.env.DEV\n ? (panelPluginModules as PluginSource[])\n : await fetchProductionSources();\n const unique = new Map<string, PluginSource>();\n for (const source of discovered) {\n const metadata = normalizeMetadata(source.metadata);\n if (!metadata || metadata.enabled === false || unique.has(metadata.id)) continue;\n unique.set(metadata.id, { ...source, metadata });\n }\n return [...unique.values()].sort(compareSources);\n}\n\nfunction resolveSourceGraph(discovered: readonly PluginSource[]) {\n return resolvePluginDependencyOrder(discovered, {\n id: (source) => source.metadata.id,\n dependencies: (source) => source.metadata.frontendInject,\n compare: compareSources\n });\n}\n\n/** Fetch production assets during foundation startup without evaluating plugin code. */\nfunction preloadPluginAssets(discovered: readonly PluginSource[]) {\n const links: HTMLLinkElement[] = [];\n if (!import.meta.env.DEV) {\n for (const source of resolveSourceGraph(discovered).ordered) {\n try {\n validatePluginCompatibility(source.metadata.elements);\n } catch {\n continue;\n }\n if (source.metadata.restartRequired || !source.entry) continue;\n const module = document.createElement(\"link\");\n module.rel = \"modulepreload\";\n module.href = source.entry;\n module.crossOrigin = \"anonymous\";\n document.head.appendChild(module);\n links.push(module);\n for (const href of source.styles || []) {\n const style = document.createElement(\"link\");\n style.rel = \"preload\";\n style.setAttribute(\"as\", \"style\");\n style.href = href;\n document.head.appendChild(style);\n links.push(style);\n }\n }\n }\n return () => links.forEach((link) => link.remove());\n}\n\n/** Preparation never rejects, so an optional download failure cannot abort the batch. */\nasync function preparePlugin(source: PluginSource, cacheKey?: string): Promise<PreparedPlugin> {\n let removeStyles: (() => void) | undefined;\n try {\n validatePluginCompatibility(source.metadata.elements);\n if (source.metadata.restartRequired)\n throw new Error(\"The plugin backend requires a restart before this version can load.\");\n const [styles, entry] = await Promise.allSettled([\n import.meta.env.DEV ? Promise.resolve(undefined) : loadStyles(source),\n Promise.resolve().then(() => source.load(cacheKey))\n ]);\n if (styles.status === \"rejected\") throw styles.reason;\n removeStyles = styles.value;\n if (entry.status === \"rejected\") throw entry.reason;\n const module = toModule(entry.value, source.metadata.id);\n if (!module)\n throw new Error(`Panel frontend plugin has no apply() export: ${source.metadata.id}`);\n return { module, removeStyles };\n } catch (error) {\n removeStyles?.();\n return { error: error instanceof Error ? error : new Error(String(error)) };\n }\n}\n\nfunction recordGraphFailure(source: PluginSource, error: Error) {\n const existing = plugins.find((plugin) => plugin.metadata.id === source.metadata.id);\n if (existing) {\n existing.error = error;\n existing.state = \"failed\";\n notifyPluginDiagnostics();\n return existing;\n }\n const plugin = shallowReactive<InternalPlugin>({\n source,\n metadata: source.metadata,\n directory: source.directory,\n revision: source.revision,\n state: \"failed\",\n requiredServices: [],\n missingServices: [],\n error\n });\n plugins.push(plugin);\n notifyPluginDiagnostics();\n return plugin;\n}\n\nasync function install(\n source: PluginSource,\n cacheKey?: string,\n configOverride?: unknown,\n prepared?: PreparedPlugin\n) {\n const existing = plugins.find((plugin) => plugin.metadata.id === source.metadata.id);\n if (existing) return existing;\n\n const unavailableDependencies = (source.metadata.frontendInject || []).filter(\n (id) => plugins.find((plugin) => plugin.metadata.id === id)?.state !== \"active\"\n );\n if (unavailableDependencies.length) {\n if (prepared && \"module\" in prepared) prepared.removeStyles?.();\n return recordGraphFailure(\n source,\n new Error(\n `Frontend plugin dependencies are not active: ${unavailableDependencies.join(\", \")}`\n )\n );\n }\n\n const plugin = shallowReactive<InternalPlugin>({\n source,\n metadata: source.metadata,\n directory: source.directory,\n revision: source.revision,\n state: \"loading\",\n requiredServices: [],\n missingServices: []\n });\n plugins.push(plugin);\n notifyPluginDiagnostics();\n try {\n const resources = prepared ?? (await preparePlugin(source, cacheKey));\n if (\"error\" in resources) throw resources.error;\n plugin.removeStyles = resources.removeStyles;\n const { module } = resources;\n plugin.requiredServices = requiredServices(module);\n {\n // An `async apply()` is awaited here, so a plugin is fully applied before\n // the next one activates and before the app is mounted. Resource loading\n // happens in parallel before this dependency-ordered activation phase.\n //\n // cordis catches a synchronous throw from `apply()` and cancels the scope\n // itself, so the wrapper keeps a copy of it: without that, a plugin that\n // failed on its first line would still be reported as loaded.\n let applied: unknown;\n let thrown: unknown;\n // The manifest id is the plugin's name, so `ctx.name` — which is what\n // appears in its log lines — always matches the package metadata.\n plugin.fork = ctx.plugin(\n {\n ...module,\n name: source.metadata.id,\n apply: (...args) => {\n try {\n return (applied = module.apply(...args));\n } catch (error) {\n thrown = error;\n throw error;\n }\n }\n },\n configOverride === undefined\n ? (source.metadata as { config?: unknown }).config\n : configOverride\n );\n if (thrown) throw thrown;\n await applied;\n ctx.logger(\"plugin\").info(`Panel frontend plugin loaded: ${source.metadata.id}`);\n }\n } catch (error: any) {\n // Failure is atomic: whatever the plugin managed to register before it threw\n // goes with its scope, so a half-loaded plugin never stays behind.\n plugin.error = error instanceof Error ? error : new Error(String(error));\n plugin.fork?.dispose();\n plugin.fork = undefined;\n plugin.removeStyles?.();\n ctx\n .logger(\"plugin\")\n .error(`Panel frontend plugin failed to load: ${source.metadata.id}`, error);\n }\n notifyPluginDiagnostics();\n return plugin;\n}\n\nfunction isCurrentRoute(plugin: InternalPlugin) {\n const vue = ctx.get(\"vue\");\n const routes = ctx.get(\"routes\");\n if (!vue || !routes) return false;\n return vue.router.currentRoute.value.matched.some(\n (record) => routes.ownerOf(record.path) === plugin.metadata.id\n );\n}\n\nasync function unloadPluginInternal(id: string, replacing = false, preserveStyles?: Set<Element>) {\n if (ESSENTIAL_PLUGIN_IDS.has(id) && !replacing) {\n throw new Error(`The essential frontend plugin \"${id}\" cannot be unloaded.`);\n }\n const plugin = plugins.find((candidate) => candidate.metadata.id === id);\n if (!plugin) return false;\n plugin.state = \"unloading\";\n notifyPluginDiagnostics();\n // Leave the plugin's page before its routes go, or the router lands on\n // nothing.\n const vue = ctx.get(\"vue\");\n if (!replacing && vue && isCurrentRoute(plugin)) await vue.router.replace(\"/404\");\n plugin.fork?.dispose();\n try {\n await settle();\n } catch (error) {\n plugin.error = error instanceof Error ? error : new Error(String(error));\n throw error;\n }\n plugin.removeStyles?.();\n removePluginStyles(plugin.source, preserveStyles);\n const index = plugins.indexOf(plugin);\n if (index >= 0) plugins.splice(index, 1);\n notifyPluginDiagnostics();\n ctx.logger(\"plugin\").info(`Panel frontend plugin unloaded: ${id}`);\n return true;\n}\n\nasync function loadPluginInternal(id: string) {\n let source = sources.get(id);\n if (!source && !import.meta.env.DEV) {\n await refreshPluginsInternal();\n source = sources.get(id);\n }\n if (!source) throw new Error(`Panel frontend plugin not found: ${id}`);\n return install(source);\n}\n\nasync function reloadPluginInternal(id: string) {\n if (ESSENTIAL_PLUGIN_IDS.has(id)) {\n await refreshPluginsInternal(undefined, true);\n return plugins.find((plugin) => plugin.metadata.id === id);\n }\n await unloadPluginInternal(id);\n if (!import.meta.env.DEV) {\n const discovered = await discoverSources();\n sources.clear();\n discovered.forEach((source) => sources.set(source.metadata.id, source));\n }\n const source = sources.get(id);\n if (!source) throw new Error(`Panel frontend plugin not found: ${id}`);\n // The server revision is the cache identity. Reloading unchanged code still\n // retries activation without manufacturing an unbounded timestamp URL.\n return install(source, source.revision || String(source.metadata.version || \"reload\"));\n}\n\n/** Re-reads what is installed and loads or unloads to match. */\nasync function refreshPluginsInternal(discovered?: PluginSource[], forceFoundations = false) {\n discovered ??= await discoverSources();\n const next = new Map(discovered.map((source) => [source.metadata.id, source]));\n sources.clear();\n next.forEach((source, id) => sources.set(id, source));\n const changedSource = (source: PluginSource, current: InternalPlugin) =>\n source.revision !== current.source.revision ||\n JSON.stringify(source.metadata) !== JSON.stringify(current.metadata);\n const reloadFoundations =\n forceFoundations ||\n discovered.some((source) => {\n const current = plugins.find((plugin) => plugin.metadata.id === source.metadata.id);\n return (\n current &&\n ESSENTIAL_PLUGIN_IDS.has(source.metadata.id) &&\n !source.metadata.restartRequired &&\n (changedSource(source, current) || pluginError(current))\n );\n });\n if (reloadFoundations) {\n const graph = resolveSourceGraph(discovered);\n for (const id of ESSENTIAL_PLUGIN_IDS) {\n const source = next.get(id);\n if (!source || graph.issues.has(id) || source.metadata.restartRequired)\n throw new Error(`Panel frontend foundation is unavailable for reload: ${id}`);\n }\n // Download before unloading the shell so a failed foundation download\n // leaves the current application usable. Keep the new stylesheet nodes\n // while removing links owned by the previous generation.\n const previousStyles = new Set(document.querySelectorAll(\"style, link[rel='stylesheet']\"));\n const ordered = [\n ...[...ESSENTIAL_PLUGIN_IDS].map((id) => next.get(id)!),\n ...graph.ordered.filter((source) => !ESSENTIAL_PLUGIN_IDS.has(source.metadata.id))\n ];\n const prepared = await Promise.all(ordered.map((source) => preparePlugin(source)));\n const failedFoundation = prepared.find(\n (result, index) => \"error\" in result && ESSENTIAL_PLUGIN_IDS.has(ordered[index].metadata.id)\n );\n if (failedFoundation && \"error\" in failedFoundation) {\n for (const result of prepared) if (\"module\" in result) result.removeStyles?.();\n throw failedFoundation.error;\n }\n const preserveStyles = new Set(\n [...document.querySelectorAll(\"style, link[rel='stylesheet']\")].filter(\n (element) => !previousStyles.has(element)\n )\n );\n const location = ctx.get(\"vue\")?.router.currentRoute.value.fullPath;\n // Hold ready hooks until the replacement shell is mounted. Cordis otherwise\n // runs them immediately because this container has already been started.\n const started = ctx.lifecycle.isActive;\n ctx.lifecycle.isActive = false;\n try {\n for (const plugin of [...plugins].reverse())\n await unloadPluginInternal(plugin.metadata.id, true, preserveStyles);\n for (const [index, source] of ordered.entries()) {\n await install(source, undefined, undefined, prepared[index]);\n await settle();\n }\n for (const [id, issue] of graph.issues) {\n const source = next.get(id);\n if (source) recordGraphFailure(source, new Error(issue.message));\n }\n auditFrontendPlugins();\n // The console mounts after feature routes and the restored session exist,\n // just as on initial startup. Keep the user's page across the remount.\n await ctx.parallel(\"plugins/loaded\");\n const router = ctx.get(\"vue\")?.router;\n if (location && router) await router.replace(location);\n await settle();\n notifyPluginDiagnostics();\n return discovered.map((source) => source.metadata);\n } finally {\n if (started) await ctx.start();\n }\n }\n for (const plugin of [...plugins].reverse()) {\n if (ESSENTIAL_PLUGIN_IDS.has(plugin.metadata.id)) continue;\n if (!next.has(plugin.metadata.id)) await unloadPluginInternal(plugin.metadata.id);\n }\n const graph = resolveSourceGraph(discovered);\n for (const [id, issue] of graph.issues) {\n const source = next.get(id);\n if (!source) continue;\n const current = plugins.find((plugin) => plugin.metadata.id === id);\n if (current && !ESSENTIAL_PLUGIN_IDS.has(id)) await unloadPluginInternal(id);\n recordGraphFailure(source, new Error(issue.message));\n }\n const pending: PluginSource[] = [];\n for (const source of graph.ordered) {\n const current = plugins.find((plugin) => plugin.metadata.id === source.metadata.id);\n if (current) current.restartRequired = Boolean(source.metadata.restartRequired);\n const changed =\n current &&\n (changedSource(source, current) ||\n Boolean(source.metadata.restartRequired) !==\n Boolean(current.source.metadata.restartRequired));\n if (current && (changed || source.metadata.restartRequired)) {\n if (ESSENTIAL_PLUGIN_IDS.has(source.metadata.id) || source.metadata.restartRequired) {\n current.restartRequired = Boolean(source.metadata.restartRequired);\n current.reloadRequired = Boolean(changed && ESSENTIAL_PLUGIN_IDS.has(source.metadata.id));\n continue;\n }\n await unloadPluginInternal(source.metadata.id);\n }\n if (!plugins.some((plugin) => plugin.metadata.id === source.metadata.id)) pending.push(source);\n }\n const prepared = await Promise.all(pending.map((source) => preparePlugin(source)));\n for (const [index, source] of pending.entries()) {\n await install(source, undefined, undefined, prepared[index]);\n }\n await settle();\n notifyPluginDiagnostics();\n return discovered.map((source) => source.metadata) as readonly PanelFrontendPluginMetadata[];\n}\n\n/** Discover once, prefetch assets, then activate foundations before the remaining batch. */\nexport async function bootstrapPanelFrontendPlugins() {\n const discovered = await discoverSources();\n sources.clear();\n discovered.forEach((source) => sources.set(source.metadata.id, source));\n const removePreloads = preloadPluginAssets(discovered);\n try {\n for (const id of ESSENTIAL_PLUGIN_IDS) {\n const source = sources.get(id);\n if (!source) throw new Error(`Panel frontend foundation plugin not found: ${id}`);\n const plugin = await install(source);\n if (plugin.error) throw plugin.error;\n if (!plugin.fork || !ctx.get(FOUNDATION_SERVICES[id])) {\n throw new Error(`Panel frontend foundation plugin failed to initialize: ${id}`);\n }\n }\n await refreshPluginsInternal(discovered);\n window.dispatchEvent(new CustomEvent(\"elementspanel:plugins-changed\"));\n } finally {\n removePreloads();\n }\n}\n\nexport function getLoadedPlugins(): readonly LoadedPanelFrontendPlugin[] {\n return plugins;\n}\n\nexport function getPluginDiagnostics(): readonly PanelFrontendPluginDiagnostic[] {\n return plugins.map((plugin) => {\n const error = pluginError(plugin);\n return {\n id: plugin.metadata.id,\n state: plugin.state,\n required: Boolean(plugin.metadata.frontendRequired),\n revision: plugin.revision,\n requiredServices: [...plugin.requiredServices],\n missingServices: [...plugin.missingServices],\n ...(error ? { error: error.message } : {})\n };\n });\n}\n\nexport function auditFrontendPlugins() {\n notifyPluginDiagnostics();\n const failures = getPluginDiagnostics().filter(\n (plugin) => plugin.required && plugin.state !== \"active\"\n );\n if (!failures.length) return;\n throw new Error(\n `Required frontend plugins are not active: ${failures\n .map((plugin) => `${plugin.id} (${plugin.state}${plugin.error ? `: ${plugin.error}` : \"\"})`)\n .join(\", \")}`\n );\n}\n\n/** Serialize UI actions and server notifications against the same browser state. */\nexport const unloadPlugin = (id: string) => change(() => unloadPluginInternal(id));\nexport const loadPlugin = (id: string) => change(() => loadPluginInternal(id));\nexport const reloadPlugin = (id: string) => change(() => reloadPluginInternal(id));\nexport const refreshPlugins = () =>\n change(async () => {\n const result = await refreshPluginsInternal();\n window.dispatchEvent(new CustomEvent(\"elementspanel:plugins-changed\"));\n return result;\n });\n\n/** Reconnect receives the complete current generation; no event history is needed. */\nexport function watchPluginChanges(): () => void {\n if (import.meta.env.DEV || typeof EventSource === \"undefined\") return () => {};\n const events = new EventSource(new URL(\"plugins/events\", document.baseURI).href);\n let revision = \"\";\n let stopped = false;\n let retry: ReturnType<typeof setTimeout> | undefined;\n const synchronize = () => {\n if (stopped) return;\n void refreshPlugins().catch((error) => {\n ctx.logger(\"plugin\").error(\"Failed to synchronize plugins\", error);\n retry = setTimeout(synchronize, 2000);\n });\n };\n events.onmessage = (event) => {\n let next: string;\n try {\n next = JSON.parse(event.data).revision;\n } catch {\n return;\n }\n if (typeof next !== \"string\" || next === revision || stopped) return;\n revision = next;\n if (retry) clearTimeout(retry);\n synchronize();\n };\n return () => {\n stopped = true;\n if (retry) clearTimeout(retry);\n events.close();\n };\n}\n","import { ctx } from \"./context\";\nimport {\n bootstrapPanelFrontendPlugins,\n auditFrontendPlugins,\n getPluginDiagnostics,\n getLoadedPlugins,\n loadPlugin,\n refreshPlugins,\n reloadPlugin,\n unloadPlugin,\n watchPluginChanges\n} from \"./loader\";\n\ndeclare global {\n interface Window {\n ElementsPanelPlugins?: {\n load: typeof loadPlugin;\n unload: typeof unloadPlugin;\n reload: typeof reloadPlugin;\n refresh: typeof refreshPlugins;\n loaded: typeof getLoadedPlugins;\n diagnostics: typeof getPluginDiagnostics;\n audit: typeof auditFrontendPlugins;\n };\n }\n}\n\nexport async function setupPanelFrontendPlugins() {\n ctx.provide(\"plugins\", undefined, true);\n ctx.set(\"plugins\", {\n get loaded() {\n return getLoadedPlugins();\n },\n get diagnostics() {\n return getPluginDiagnostics();\n },\n load: loadPlugin,\n unload: unloadPlugin,\n reload: reloadPlugin,\n refresh: refreshPlugins,\n audit: auditFrontendPlugins\n });\n\n await bootstrapPanelFrontendPlugins();\n auditFrontendPlugins();\n\n window.ElementsPanelPlugins = {\n load: loadPlugin,\n unload: unloadPlugin,\n reload: reloadPlugin,\n refresh: refreshPlugins,\n loaded: getLoadedPlugins,\n diagnostics: getPluginDiagnostics,\n audit: auditFrontendPlugins\n };\n await ctx.parallel(\"plugins/loaded\");\n await ctx.start();\n ctx.effect(watchPluginChanges);\n}\n","import { ctx } from \"./plugin/context\";\nimport { setupPanelFrontendPlugins } from \"./plugin/install\";\n\nsetupPanelFrontendPlugins().catch(async (error) => {\n console.error(\"Plugin startup failed:\", error);\n const startup = ctx.get(\"startup\");\n if (startup) startup.showError(error);\n else {\n const host = window as Window & { setAppLoadingError?: (message: string) => void };\n host.setAppLoadingError?.(error instanceof Error ? error.message : String(error));\n }\n await ctx.stop();\n});\n"],"file":"assets/index-1da88aed.js"}
|