@aiot-nexus/plugin-sdk 1.0.0

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.
Files changed (47) hide show
  1. package/README.md +74 -0
  2. package/dev-host/host.html +344 -0
  3. package/dev-host/main.js +694 -0
  4. package/dev-host/preload.js +22 -0
  5. package/dist/.generated/plugin-framework-version.d.ts +11 -0
  6. package/dist/.generated/plugin-framework-version.js +39 -0
  7. package/dist/.generated/plugin-manifest.schema.json +106 -0
  8. package/dist/browser/frame-client.d.ts +26 -0
  9. package/dist/browser/frame-client.mjs +239 -0
  10. package/dist/src/browser/frame-client.d.ts +26 -0
  11. package/dist/src/browser/frame-client.js +244 -0
  12. package/dist/src/cli/run.d.ts +7 -0
  13. package/dist/src/cli/run.js +270 -0
  14. package/dist/src/cli.d.ts +2 -0
  15. package/dist/src/cli.js +9 -0
  16. package/dist/src/dev.d.ts +36 -0
  17. package/dist/src/dev.js +224 -0
  18. package/dist/src/index.d.ts +7 -0
  19. package/dist/src/index.js +27 -0
  20. package/dist/src/scaffold.d.ts +23 -0
  21. package/dist/src/scaffold.js +306 -0
  22. package/dist/src/types.d.ts +142 -0
  23. package/dist/src/types.js +2 -0
  24. package/dist/src/validation.d.ts +9 -0
  25. package/dist/src/validation.js +160 -0
  26. package/package.json +47 -0
  27. package/templates/minimal/.gitignore.tmpl +4 -0
  28. package/templates/minimal/.vscode/launch.json +22 -0
  29. package/templates/minimal/README.md.tmpl +22 -0
  30. package/templates/minimal/scripts/build.js.tmpl +83 -0
  31. package/templates/minimal/src/main.ts.tmpl +23 -0
  32. package/templates/minimal/src/renderer/app.ts.tmpl +194 -0
  33. package/templates/minimal/src/renderer/index.html +34 -0
  34. package/templates/minimal/src/renderer/plugin.css +164 -0
  35. package/templates/minimal/tsconfig.main.json +15 -0
  36. package/templates/minimal/tsconfig.renderer.json +17 -0
  37. package/templates/sqlite/.gitignore.tmpl +4 -0
  38. package/templates/sqlite/.vscode/launch.json +22 -0
  39. package/templates/sqlite/README.md.tmpl +22 -0
  40. package/templates/sqlite/scripts/build.js.tmpl +143 -0
  41. package/templates/sqlite/src/better-sqlite3.d.ts +22 -0
  42. package/templates/sqlite/src/main.ts.tmpl +190 -0
  43. package/templates/sqlite/src/renderer/app.ts.tmpl +428 -0
  44. package/templates/sqlite/src/renderer/index.html +57 -0
  45. package/templates/sqlite/src/renderer/plugin.css +275 -0
  46. package/templates/sqlite/tsconfig.main.json +15 -0
  47. package/templates/sqlite/tsconfig.renderer.json +17 -0
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-var-requires */
3
+
4
+ const { contextBridge, ipcRenderer } = require("electron");
5
+
6
+ const ipcChannels = {
7
+ getConfig: "nexus-plugin-dev:get-config",
8
+ invoke: "nexus-plugin-dev:invoke",
9
+ frameReady: "nexus-plugin-dev:frame-ready"
10
+ };
11
+
12
+ contextBridge.exposeInMainWorld("nexusPluginDevHost", {
13
+ getConfig: function getConfig() {
14
+ return ipcRenderer.invoke(ipcChannels.getConfig);
15
+ },
16
+ invoke: function invoke(request) {
17
+ return ipcRenderer.invoke(ipcChannels.invoke, request);
18
+ },
19
+ notifyFrameReady: function notifyFrameReady() {
20
+ ipcRenderer.send(ipcChannels.frameReady);
21
+ }
22
+ });
@@ -0,0 +1,11 @@
1
+ export declare const PLUGIN_FRAMEWORK_VERSION = "1.0.0";
2
+ export declare const PLUGIN_MANIFEST_SCHEMA_VERSION = 1;
3
+ export declare const PLUGIN_COMPATIBLE_VERSION_PATTERN = "^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))?(\\.(0|[1-9][0-9]*))?$";
4
+ export interface ParsedPluginVersion {
5
+ major: number;
6
+ minor: number;
7
+ patch: number;
8
+ }
9
+ export declare function parsePluginCompatibleVersion(value: string): ParsedPluginVersion | undefined;
10
+ export declare function comparePluginVersions(left: string, right: string): number | undefined;
11
+ export declare function isPluginFrameworkVersionCompatible(requiredVersion: string, supportedVersion?: string): boolean;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isPluginFrameworkVersionCompatible = exports.comparePluginVersions = exports.parsePluginCompatibleVersion = exports.PLUGIN_COMPATIBLE_VERSION_PATTERN = exports.PLUGIN_MANIFEST_SCHEMA_VERSION = exports.PLUGIN_FRAMEWORK_VERSION = void 0;
4
+ exports.PLUGIN_FRAMEWORK_VERSION = "1.0.0";
5
+ exports.PLUGIN_MANIFEST_SCHEMA_VERSION = 1;
6
+ exports.PLUGIN_COMPATIBLE_VERSION_PATTERN = "^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))?(\\.(0|[1-9][0-9]*))?$";
7
+ function parsePluginCompatibleVersion(value) {
8
+ const match = /^(0|[1-9][0-9]*)(?:\.(0|[1-9][0-9]*))?(?:\.(0|[1-9][0-9]*))?$/.exec(value.trim());
9
+ if (!match) {
10
+ return undefined;
11
+ }
12
+ const segments = [Number(match[1]), Number(match[2] || 0), Number(match[3] || 0)];
13
+ if (segments.some((segment) => !Number.isSafeInteger(segment))) {
14
+ return undefined;
15
+ }
16
+ return { major: segments[0], minor: segments[1], patch: segments[2] };
17
+ }
18
+ exports.parsePluginCompatibleVersion = parsePluginCompatibleVersion;
19
+ function comparePluginVersions(left, right) {
20
+ const leftVersion = parsePluginCompatibleVersion(left);
21
+ const rightVersion = parsePluginCompatibleVersion(right);
22
+ if (!leftVersion || !rightVersion) {
23
+ return undefined;
24
+ }
25
+ for (const key of ["major", "minor", "patch"]) {
26
+ const difference = leftVersion[key] - rightVersion[key];
27
+ if (difference !== 0) {
28
+ return difference;
29
+ }
30
+ }
31
+ return 0;
32
+ }
33
+ exports.comparePluginVersions = comparePluginVersions;
34
+ function isPluginFrameworkVersionCompatible(requiredVersion, supportedVersion = exports.PLUGIN_FRAMEWORK_VERSION) {
35
+ const required = parsePluginCompatibleVersion(requiredVersion);
36
+ const supported = parsePluginCompatibleVersion(supportedVersion);
37
+ return Boolean(required && supported && required.major === supported.major && required.minor <= supported.minor);
38
+ }
39
+ exports.isPluginFrameworkVersionCompatible = isPluginFrameworkVersionCompatible;
@@ -0,0 +1,106 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://aiot-nexus.local/schemas/plugin-manifest.schema.json",
4
+ "title": "AIoT Nexus Plugin Manifest",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schemaVersion",
9
+ "pluginId",
10
+ "displayNameKey",
11
+ "descriptionKey",
12
+ "pluginVersion",
13
+ "hostApiVersion",
14
+ "minHostVersion",
15
+ "supportedCultures",
16
+ "permissions"
17
+ ],
18
+ "properties": {
19
+ "schemaVersion": { "const": 1 },
20
+ "pluginId": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]{1,63}$" },
21
+ "displayNameKey": { "type": "string", "minLength": 1 },
22
+ "descriptionKey": { "type": "string" },
23
+ "pluginVersion": { "type": "string", "minLength": 1 },
24
+ "hostApiVersion": { "type": "string", "pattern": "^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))?(\\.(0|[1-9][0-9]*))?$" },
25
+ "minHostVersion": { "type": "string", "pattern": "^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))?(\\.(0|[1-9][0-9]*))?$" },
26
+ "supportedCultures": {
27
+ "type": "array",
28
+ "items": { "type": "string", "minLength": 2 },
29
+ "uniqueItems": true
30
+ },
31
+ "mainEntry": { "type": "string", "minLength": 1 },
32
+ "rendererEntry": { "type": "string", "minLength": 1 },
33
+ "permissions": {
34
+ "type": "array",
35
+ "items": {
36
+ "enum": ["businessLog", "settings", "filesystem", "udp", "serial", "externalProcess", "dialog"]
37
+ },
38
+ "uniqueItems": true
39
+ },
40
+ "deferred": { "type": "boolean" },
41
+ "resources": {
42
+ "type": "object",
43
+ "additionalProperties": {
44
+ "type": "object",
45
+ "additionalProperties": { "type": "string" }
46
+ }
47
+ },
48
+ "businessEntries": {
49
+ "type": "array",
50
+ "items": { "$ref": "#/$defs/businessEntry" }
51
+ },
52
+ "tools": {
53
+ "type": "array",
54
+ "items": { "$ref": "#/$defs/tool" }
55
+ },
56
+ "settingsSections": {
57
+ "type": "array",
58
+ "items": { "$ref": "#/$defs/settingsSection" }
59
+ }
60
+ },
61
+ "$defs": {
62
+ "businessEntry": {
63
+ "type": "object",
64
+ "additionalProperties": false,
65
+ "required": ["businessId", "titleKey", "iconKey", "section", "order", "component"],
66
+ "properties": {
67
+ "businessId": { "type": "string", "minLength": 1 },
68
+ "titleKey": { "type": "string", "minLength": 1 },
69
+ "descriptionKey": { "type": "string" },
70
+ "iconKey": { "type": "string", "minLength": 1 },
71
+ "section": { "type": "string", "minLength": 1 },
72
+ "order": { "type": "number" },
73
+ "component": { "type": "string", "minLength": 1 },
74
+ "pageRoute": { "type": "string", "minLength": 1 },
75
+ "isFullBleed": { "type": "boolean" },
76
+ "showBusinessLogToggle": { "type": "boolean" }
77
+ }
78
+ },
79
+ "tool": {
80
+ "type": "object",
81
+ "additionalProperties": false,
82
+ "required": ["toolId", "titleKey", "iconKey", "navGroup", "order", "component"],
83
+ "properties": {
84
+ "toolId": { "type": "string", "minLength": 1 },
85
+ "titleKey": { "type": "string", "minLength": 1 },
86
+ "descriptionKey": { "type": "string" },
87
+ "iconKey": { "type": "string", "minLength": 1 },
88
+ "navGroup": { "type": "string", "minLength": 1 },
89
+ "order": { "type": "number" },
90
+ "component": { "type": "string", "minLength": 1 }
91
+ }
92
+ },
93
+ "settingsSection": {
94
+ "type": "object",
95
+ "additionalProperties": false,
96
+ "required": ["sectionId", "titleKey", "order", "component"],
97
+ "properties": {
98
+ "sectionId": { "type": "string", "minLength": 1 },
99
+ "titleKey": { "type": "string", "minLength": 1 },
100
+ "descriptionKey": { "type": "string" },
101
+ "order": { "type": "number" },
102
+ "component": { "type": "string", "minLength": 1 }
103
+ }
104
+ }
105
+ }
106
+ }
@@ -0,0 +1,26 @@
1
+ import type { BusinessLogAppendRequest, BusinessLogEntry, NexusResult, PluginRendererContext, PluginRendererMethod, PluginSettingsDocument } from "../types";
2
+ export type PluginFrameClientErrorCode = "Disposed" | "ProtocolError" | "RequestTimeout";
3
+ export declare class PluginFrameClientError extends Error {
4
+ readonly code: PluginFrameClientErrorCode;
5
+ constructor(code: PluginFrameClientErrorCode, message: string);
6
+ }
7
+ export interface PluginFrameClientOptions {
8
+ frameWindow?: Window;
9
+ targetWindow?: Window;
10
+ requestTimeoutMs?: number;
11
+ autoResize?: boolean;
12
+ resizeRoot?: HTMLElement;
13
+ }
14
+ export type PluginFrameContextListener = (context: PluginRendererContext) => void;
15
+ export interface PluginFrameClient {
16
+ waitForContext(): Promise<PluginRendererContext>;
17
+ onContextChanged(listener: PluginFrameContextListener): () => void;
18
+ request<TResult>(method: PluginRendererMethod, params?: Record<string, unknown>): Promise<NexusResult<TResult>>;
19
+ getSettings(): Promise<NexusResult<PluginSettingsDocument>>;
20
+ updateSettings(values: Record<string, unknown>): Promise<NexusResult<PluginSettingsDocument>>;
21
+ appendLog(request: BusinessLogAppendRequest): Promise<NexusResult<BusinessLogEntry>>;
22
+ invokeMain<TInput extends Record<string, unknown>, TResult>(operation: string, input?: TInput): Promise<NexusResult<TResult>>;
23
+ notifyResize(): void;
24
+ dispose(): void;
25
+ }
26
+ export declare function createPluginFrameClient(options?: PluginFrameClientOptions): PluginFrameClient;
@@ -0,0 +1,239 @@
1
+ const initMessageType = "nexus-plugin:init";
2
+ const contextChangedMessageType = "nexus-plugin:context-changed";
3
+ const readyMessageType = "nexus-plugin:ready";
4
+ const requestMessageType = "nexus-plugin:request";
5
+ const responseMessageType = "nexus-plugin:response";
6
+ const resizeMessageType = "nexus-plugin:resize";
7
+ const defaultRequestTimeoutMs = 15000;
8
+ export class PluginFrameClientError extends Error {
9
+ constructor(code, message) {
10
+ super(message);
11
+ this.name = "PluginFrameClientError";
12
+ this.code = code;
13
+ }
14
+ }
15
+ export function createPluginFrameClient(options = {}) {
16
+ const resolvedFrameWindow = options.frameWindow || (typeof window === "undefined" ? undefined : window);
17
+ if (!resolvedFrameWindow) {
18
+ throw new PluginFrameClientError("ProtocolError", "PluginFrame client requires a browser window.");
19
+ }
20
+ const frameWindow = resolvedFrameWindow;
21
+ const targetWindow = options.targetWindow || frameWindow.parent;
22
+ const requestTimeoutMs = options.requestTimeoutMs === undefined ? defaultRequestTimeoutMs : options.requestTimeoutMs;
23
+ if (!Number.isFinite(requestTimeoutMs) || requestTimeoutMs <= 0) {
24
+ throw new PluginFrameClientError("ProtocolError", "requestTimeoutMs must be a positive finite number.");
25
+ }
26
+ let requestSequence = 0;
27
+ let disposed = false;
28
+ let contextValue;
29
+ let hostOrigin;
30
+ let contextSettled = false;
31
+ let contextTimeoutId;
32
+ let resizeTimer;
33
+ let resizeObserver;
34
+ const pendingRequests = new Map();
35
+ const contextListeners = new Set();
36
+ let resolveContext;
37
+ let rejectContext;
38
+ const contextPromise = new Promise((resolve, reject) => {
39
+ resolveContext = resolve;
40
+ rejectContext = reject;
41
+ });
42
+ void contextPromise.catch(() => undefined);
43
+ contextTimeoutId = frameWindow.setTimeout(() => {
44
+ contextTimeoutId = undefined;
45
+ if (!contextSettled) {
46
+ contextSettled = true;
47
+ rejectContext(new PluginFrameClientError("RequestTimeout", "PluginFrame initialization timed out."));
48
+ }
49
+ }, requestTimeoutMs);
50
+ frameWindow.addEventListener("message", handleMessage);
51
+ if (options.autoResize !== false) {
52
+ frameWindow.addEventListener("resize", scheduleResize);
53
+ const ResizeObserverConstructor = frameWindow.ResizeObserver;
54
+ if (typeof ResizeObserverConstructor === "function") {
55
+ const observer = new ResizeObserverConstructor(scheduleResize);
56
+ observer.observe(options.resizeRoot || frameWindow.document.documentElement);
57
+ resizeObserver = observer;
58
+ }
59
+ }
60
+ targetWindow.postMessage({ type: readyMessageType }, "*");
61
+ function waitForContext() {
62
+ if (disposed) {
63
+ return Promise.reject(disposedError());
64
+ }
65
+ return contextValue ? Promise.resolve(contextValue) : contextPromise;
66
+ }
67
+ function onContextChanged(listener) {
68
+ if (disposed) {
69
+ throw disposedError();
70
+ }
71
+ contextListeners.add(listener);
72
+ return () => {
73
+ contextListeners.delete(listener);
74
+ };
75
+ }
76
+ async function request(method, params) {
77
+ await waitForContext();
78
+ if (disposed) {
79
+ throw disposedError();
80
+ }
81
+ const requestId = "nexus-sdk-" + Date.now() + "-" + (++requestSequence);
82
+ return new Promise((resolve, reject) => {
83
+ const timeoutId = frameWindow.setTimeout(() => {
84
+ pendingRequests.delete(requestId);
85
+ reject(new PluginFrameClientError("RequestTimeout", "PluginFrame request timed out: " + method));
86
+ }, requestTimeoutMs);
87
+ pendingRequests.set(requestId, {
88
+ resolve: (result) => resolve(result),
89
+ reject,
90
+ timeoutId
91
+ });
92
+ post({ type: requestMessageType, requestId, method, params });
93
+ });
94
+ }
95
+ function getSettings() {
96
+ return request("getSettings");
97
+ }
98
+ function updateSettings(values) {
99
+ return request("updateSettings", { values });
100
+ }
101
+ function appendLog(logRequest) {
102
+ return request("appendLog", logRequest);
103
+ }
104
+ function invokeMain(operation, input) {
105
+ return request("invokeMain", { operation, input });
106
+ }
107
+ function handleMessage(event) {
108
+ if (disposed || event.source !== targetWindow || !isRecord(event.data)) {
109
+ return;
110
+ }
111
+ if (hostOrigin !== undefined && event.origin !== hostOrigin) {
112
+ return;
113
+ }
114
+ if (event.data.type === initMessageType || event.data.type === contextChangedMessageType) {
115
+ if (!isPluginRendererContext(event.data.context)) {
116
+ return;
117
+ }
118
+ const hadContext = contextValue !== undefined;
119
+ hostOrigin = event.origin;
120
+ contextValue = event.data.context;
121
+ if (!contextSettled) {
122
+ contextSettled = true;
123
+ if (contextTimeoutId !== undefined) {
124
+ frameWindow.clearTimeout(contextTimeoutId);
125
+ contextTimeoutId = undefined;
126
+ }
127
+ resolveContext(contextValue);
128
+ }
129
+ if (hadContext) {
130
+ notifyContextChanged(contextValue);
131
+ }
132
+ scheduleResize();
133
+ return;
134
+ }
135
+ if (event.data.type !== responseMessageType || typeof event.data.requestId !== "string") {
136
+ return;
137
+ }
138
+ const pending = pendingRequests.get(event.data.requestId);
139
+ if (!pending) {
140
+ return;
141
+ }
142
+ pendingRequests.delete(event.data.requestId);
143
+ frameWindow.clearTimeout(pending.timeoutId);
144
+ if (!isNexusResult(event.data.result)) {
145
+ pending.reject(new PluginFrameClientError("ProtocolError", "PluginFrame response is malformed."));
146
+ return;
147
+ }
148
+ pending.resolve(event.data.result);
149
+ }
150
+ function notifyContextChanged(context) {
151
+ for (const listener of Array.from(contextListeners)) {
152
+ try {
153
+ listener(context);
154
+ }
155
+ catch (error) {
156
+ const logger = frameWindow.console;
157
+ logger?.error("PluginFrame context listener failed.", error);
158
+ }
159
+ }
160
+ }
161
+ function scheduleResize() {
162
+ if (disposed || !contextValue || options.autoResize === false) {
163
+ return;
164
+ }
165
+ if (resizeTimer !== undefined) {
166
+ frameWindow.clearTimeout(resizeTimer);
167
+ }
168
+ if (contextTimeoutId !== undefined) {
169
+ frameWindow.clearTimeout(contextTimeoutId);
170
+ }
171
+ resizeTimer = frameWindow.setTimeout(() => {
172
+ resizeTimer = undefined;
173
+ notifyResize();
174
+ }, 0);
175
+ }
176
+ function notifyResize() {
177
+ if (disposed || !contextValue) {
178
+ return;
179
+ }
180
+ const root = options.resizeRoot || frameWindow.document.documentElement;
181
+ const body = frameWindow.document.body;
182
+ const height = Math.max(root.scrollHeight, root.offsetHeight, body?.scrollHeight || 0, body?.offsetHeight || 0);
183
+ post({ type: resizeMessageType, height });
184
+ }
185
+ function post(message) {
186
+ targetWindow.postMessage(message, hostOrigin && hostOrigin !== "null" ? hostOrigin : "*");
187
+ }
188
+ function dispose() {
189
+ if (disposed) {
190
+ return;
191
+ }
192
+ disposed = true;
193
+ frameWindow.removeEventListener("message", handleMessage);
194
+ frameWindow.removeEventListener("resize", scheduleResize);
195
+ resizeObserver?.disconnect();
196
+ if (resizeTimer !== undefined) {
197
+ frameWindow.clearTimeout(resizeTimer);
198
+ }
199
+ const error = disposedError();
200
+ if (!contextSettled) {
201
+ contextSettled = true;
202
+ rejectContext(error);
203
+ }
204
+ for (const pending of pendingRequests.values()) {
205
+ frameWindow.clearTimeout(pending.timeoutId);
206
+ pending.reject(error);
207
+ }
208
+ pendingRequests.clear();
209
+ contextListeners.clear();
210
+ }
211
+ return { waitForContext, onContextChanged, request, getSettings, updateSettings, appendLog, invokeMain, notifyResize, dispose };
212
+ }
213
+ function disposedError() {
214
+ return new PluginFrameClientError("Disposed", "PluginFrame client has been disposed.");
215
+ }
216
+ function isRecord(value) {
217
+ return typeof value === "object" && value !== null && !Array.isArray(value);
218
+ }
219
+ function isPluginRendererContext(value) {
220
+ if (!isRecord(value)) {
221
+ return false;
222
+ }
223
+ return typeof value.schemaVersion === "number"
224
+ && typeof value.pluginId === "string"
225
+ && (value.surface === "business" || value.surface === "tool" || value.surface === "settings")
226
+ && typeof value.contributionId === "string"
227
+ && typeof value.language === "string"
228
+ && (value.themeMode === "light" || value.themeMode === "dark" || value.themeMode === "system")
229
+ && typeof value.hostApiVersion === "string";
230
+ }
231
+ function isNexusResult(value) {
232
+ if (!isRecord(value) || typeof value.ok !== "boolean") {
233
+ return false;
234
+ }
235
+ if (value.ok) {
236
+ return Object.prototype.hasOwnProperty.call(value, "value");
237
+ }
238
+ return isRecord(value.error) && typeof value.error.code === "string" && typeof value.error.message === "string";
239
+ }
@@ -0,0 +1,26 @@
1
+ import type { BusinessLogAppendRequest, BusinessLogEntry, NexusResult, PluginRendererContext, PluginRendererMethod, PluginSettingsDocument } from "../types";
2
+ export type PluginFrameClientErrorCode = "Disposed" | "ProtocolError" | "RequestTimeout";
3
+ export declare class PluginFrameClientError extends Error {
4
+ readonly code: PluginFrameClientErrorCode;
5
+ constructor(code: PluginFrameClientErrorCode, message: string);
6
+ }
7
+ export interface PluginFrameClientOptions {
8
+ frameWindow?: Window;
9
+ targetWindow?: Window;
10
+ requestTimeoutMs?: number;
11
+ autoResize?: boolean;
12
+ resizeRoot?: HTMLElement;
13
+ }
14
+ export type PluginFrameContextListener = (context: PluginRendererContext) => void;
15
+ export interface PluginFrameClient {
16
+ waitForContext(): Promise<PluginRendererContext>;
17
+ onContextChanged(listener: PluginFrameContextListener): () => void;
18
+ request<TResult>(method: PluginRendererMethod, params?: Record<string, unknown>): Promise<NexusResult<TResult>>;
19
+ getSettings(): Promise<NexusResult<PluginSettingsDocument>>;
20
+ updateSettings(values: Record<string, unknown>): Promise<NexusResult<PluginSettingsDocument>>;
21
+ appendLog(request: BusinessLogAppendRequest): Promise<NexusResult<BusinessLogEntry>>;
22
+ invokeMain<TInput extends Record<string, unknown>, TResult>(operation: string, input?: TInput): Promise<NexusResult<TResult>>;
23
+ notifyResize(): void;
24
+ dispose(): void;
25
+ }
26
+ export declare function createPluginFrameClient(options?: PluginFrameClientOptions): PluginFrameClient;