@ethisyscore/plugin-ui 1.123.0 → 1.125.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.
- package/README.md +1 -1
- package/dist/platform-react/index.cjs +151 -0
- package/dist/platform-react/index.cjs.map +1 -1
- package/dist/platform-react/index.d.cts +111 -1
- package/dist/platform-react/index.d.ts +111 -1
- package/dist/platform-react/index.js +143 -2
- package/dist/platform-react/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ and the shared MUI component surface externalised to the host's instances.
|
|
|
16
16
|
| Subpath | Key exports | Purpose |
|
|
17
17
|
|---|---|---|
|
|
18
18
|
| `.` | `createPortBridgeClient`, `BridgeClientContext` / `useBridgeClient`, `useBridgeTheme` / `useBridgeLocale`, `ExtensionRuntimeProvider`, `useMcpResource` / `useMcpTool` / `useMcpQuery` / `unwrapItems`, `useHostIdentity` / `useCurrentUser`, `definePlatformReactPage` / `emitNavigation` / `PlatformReactPageProps` | Bridge client + theme/locale context, brokered-MCP data hooks, host identity, and the base PlatformReact page contract |
|
|
19
|
-
| `./platform-react` | `definePlatformReactPluginPage` / `createPluginPageDefiner`, `definePlatformReactPluginOverlay` / `useOverlayHost`, `useView` / `createUseView` / `ViewComponent` / `isComponent`, `BaseMcpService` / `useToolInvoker` / `useToolInvokerMap`, `useAuthenticatedQuery` / `useAuthenticatedQueries`, `injectPluginStyles` / `PluginStyleScope`, `createReactRouterShim`, `usePluginRealtime`, `useMcpUpload`, `useManagedLifecycle` | The plugin authoring layer: page/overlay wrappers (react-query + manifest + style root), the static `useView` adapter pattern, the MCP service base + tool invokers, pre-authenticated react-query wrappers, scoped-style injection, router shim, realtime, and file upload |
|
|
19
|
+
| `./platform-react` | `definePlatformReactPluginPage` / `createPluginPageDefiner`, `definePlatformReactPluginOverlay` / `useOverlayHost`, `useView` / `createUseView` / `ViewComponent` / `isComponent`, `BaseMcpService` / `useToolInvoker` / `useToolInvokerMap`, `useAuthenticatedQuery` / `useAuthenticatedQueries`, `injectPluginStyles` / `PluginStyleScope`, `createReactRouterShim`, `usePluginRealtime`, `useBackgroundOperation` / `useOperationsByParent` / `useLatestTerminalOperationByParent` / `hasKind`, `useMcpUpload`, `useManagedLifecycle` | The plugin authoring layer: page/overlay wrappers (react-query + manifest + style root), the static `useView` adapter pattern, the MCP service base + tool invokers, pre-authenticated react-query wrappers, scoped-style injection, router shim, realtime, following the plugin's own background operations, and file upload |
|
|
20
20
|
| `./icons` | `NextureIcons`, `IconMap`, 470+ `Ni*` icon components, `sizeHelper` / `strokeSizeHelper`, `IconName` / `IconSize` / `IconVariant` | The gogo-ui "nexture" SVG icon set with props types and size/stroke helpers |
|
|
21
21
|
| `./components/ui` | `Button`, `Card`, `Dialog`, `Table`, `TextField`, `Select`, `Tabs`, `Typography`, `Grid`, `Stack`, `Menu`, `DebouncedSearchInput`, … | MUI component re-exports plus the Dialog scroll-lock wrapper and the debounced search field. These are **host externals** — never bundled; production builds bind them to the host's MUI instance |
|
|
22
22
|
| `./components/layout` | `PageHeader` / `usePageHeader` / `withPageHeader` / `buildBreadcrumbs`, `FillGrid` / `FillGridItem` / `FillGap` / `FillSpan`, sidebar-action context (`SidebarActionProvider`, `useSidebarAction` / `useSidebarActions` / `useTriggerSidebarAction`), `RouteMeta` / `RouteMetaEntry` | Layout primitives (flex-wrap grid), the page-header layer + breadcrumb builder, and the sidebar-action context/provider |
|
|
@@ -766,6 +766,147 @@ function usePluginRealtime(typeCode, handler) {
|
|
|
766
766
|
return source.subscribe(typeCode, (payload) => ref.current(payload));
|
|
767
767
|
}, [source, typeCode]);
|
|
768
768
|
}
|
|
769
|
+
|
|
770
|
+
// src/platform-react/operations/asStateChanged.ts
|
|
771
|
+
function asStateChanged(payload) {
|
|
772
|
+
if (payload == null || typeof payload !== "object") {
|
|
773
|
+
return null;
|
|
774
|
+
}
|
|
775
|
+
const candidate = payload;
|
|
776
|
+
return typeof candidate.operationId === "string" && typeof candidate.eventSequence === "number" ? candidate : null;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// src/platform-react/operations/mergeOperation.ts
|
|
780
|
+
function mergeOperation(current, event) {
|
|
781
|
+
if (current && current.eventSequence >= event.eventSequence) {
|
|
782
|
+
return current;
|
|
783
|
+
}
|
|
784
|
+
const { extensionId: _extensionId, previousStatus: _previousStatus, ...fields } = event;
|
|
785
|
+
return { ...fields, resultPayloadJson: current?.resultPayloadJson ?? null };
|
|
786
|
+
}
|
|
787
|
+
function mergeIntoList(current, event) {
|
|
788
|
+
const rows = current ?? [];
|
|
789
|
+
const index = rows.findIndex((r) => r.operationId === event.operationId);
|
|
790
|
+
if (index < 0) {
|
|
791
|
+
return [mergeOperation(null, event), ...rows];
|
|
792
|
+
}
|
|
793
|
+
const merged = mergeOperation(rows[index], event);
|
|
794
|
+
if (merged === rows[index]) {
|
|
795
|
+
return rows;
|
|
796
|
+
}
|
|
797
|
+
const next = rows.slice();
|
|
798
|
+
next[index] = merged;
|
|
799
|
+
return next;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// src/platform-react/operations/queryKeys.ts
|
|
803
|
+
var pluginOperationKeys = {
|
|
804
|
+
all: ["plugin-operations"],
|
|
805
|
+
byId: (operationId) => ["plugin-operations", "get", operationId],
|
|
806
|
+
byParent: (parentEntityType, parentEntityId) => ["plugin-operations", "by-parent", parentEntityType, parentEntityId],
|
|
807
|
+
latestTerminalByParent: (parentEntityType, parentEntityId) => ["plugin-operations", "latest-terminal", parentEntityType, parentEntityId]
|
|
808
|
+
};
|
|
809
|
+
|
|
810
|
+
// src/platform-react/operations/status.ts
|
|
811
|
+
var TERMINAL = /* @__PURE__ */ new Set(["Succeeded", "Failed", "Cancelled"]);
|
|
812
|
+
function isTerminalOperationStatus(status) {
|
|
813
|
+
return status != null && TERMINAL.has(status);
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// src/platform-react/operations/types.ts
|
|
817
|
+
var PLUGIN_OPERATION_STATE_CHANGED = "operations.plugin-operation.state-changed";
|
|
818
|
+
var PLUGIN_OPERATION_TOOLS = {
|
|
819
|
+
get: "plugin-operations:get",
|
|
820
|
+
listByParent: "plugin-operations:list-by-parent",
|
|
821
|
+
listActive: "plugin-operations:list-active",
|
|
822
|
+
latestTerminalByParent: "plugin-operations:latest-terminal-by-parent"
|
|
823
|
+
};
|
|
824
|
+
var OPERATION_FALLBACK_POLL_MS = 8e3;
|
|
825
|
+
|
|
826
|
+
// src/platform-react/operations/useBackgroundOperation.ts
|
|
827
|
+
function useBackgroundOperation(operationId) {
|
|
828
|
+
const queryClient = reactQuery.useQueryClient();
|
|
829
|
+
const realtime = extensionRuntime.usePluginRealtimeSource();
|
|
830
|
+
const { invoke } = extensionRuntime.useMcpTool(PLUGIN_OPERATION_TOOLS.get);
|
|
831
|
+
const query = reactQuery.useQuery({
|
|
832
|
+
queryKey: pluginOperationKeys.byId(operationId ?? ""),
|
|
833
|
+
enabled: Boolean(operationId),
|
|
834
|
+
// Never undefined: TanStack Query rejects an undefined result.
|
|
835
|
+
queryFn: async () => await invoke({ operationId }) ?? null,
|
|
836
|
+
refetchInterval: (q) => realtime === null && q.state.data != null && !isTerminalOperationStatus(q.state.data.status) ? OPERATION_FALLBACK_POLL_MS : false
|
|
837
|
+
});
|
|
838
|
+
usePluginRealtime(PLUGIN_OPERATION_STATE_CHANGED, (payload) => {
|
|
839
|
+
const event = asStateChanged(payload);
|
|
840
|
+
if (!operationId || event?.operationId !== operationId) {
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
const key = pluginOperationKeys.byId(operationId);
|
|
844
|
+
const before = queryClient.getQueryData(key);
|
|
845
|
+
const merged = mergeOperation(before, event);
|
|
846
|
+
queryClient.setQueryData(key, merged);
|
|
847
|
+
if (merged !== before && isTerminalOperationStatus(merged.status)) {
|
|
848
|
+
void queryClient.invalidateQueries({ queryKey: key });
|
|
849
|
+
}
|
|
850
|
+
});
|
|
851
|
+
return query;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// src/platform-react/operations/hasKind.ts
|
|
855
|
+
var KIND_SCOPE = /^p:[0-9a-f]{32}:/i;
|
|
856
|
+
var PARENT_SCOPE = /^po:[0-9A-F]{32}:/i;
|
|
857
|
+
function hasKind(operation, unscopedKind) {
|
|
858
|
+
const kind = typeof operation === "string" ? operation : operation?.kind;
|
|
859
|
+
return kind != null && kind.replace(KIND_SCOPE, "") === unscopedKind;
|
|
860
|
+
}
|
|
861
|
+
function hasParentEntityType(operation, unscopedParentEntityType) {
|
|
862
|
+
const parentType = typeof operation === "string" ? operation : operation?.parentEntityType;
|
|
863
|
+
return parentType != null && parentType.replace(PARENT_SCOPE, "") === unscopedParentEntityType;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// src/platform-react/operations/useOperationsByParent.ts
|
|
867
|
+
function useOperationsByParent(parentEntityType, parentEntityId) {
|
|
868
|
+
const queryClient = reactQuery.useQueryClient();
|
|
869
|
+
const realtime = extensionRuntime.usePluginRealtimeSource();
|
|
870
|
+
const { invoke } = extensionRuntime.useMcpTool(
|
|
871
|
+
PLUGIN_OPERATION_TOOLS.listByParent
|
|
872
|
+
);
|
|
873
|
+
const query = reactQuery.useQuery({
|
|
874
|
+
queryKey: pluginOperationKeys.byParent(parentEntityType, parentEntityId ?? ""),
|
|
875
|
+
enabled: Boolean(parentEntityId),
|
|
876
|
+
queryFn: async () => (await invoke({ parentEntityType, parentEntityId }))?.items ?? [],
|
|
877
|
+
refetchInterval: (q) => realtime === null && (q.state.data ?? []).some((op) => !isTerminalOperationStatus(op.status)) ? OPERATION_FALLBACK_POLL_MS : false
|
|
878
|
+
});
|
|
879
|
+
usePluginRealtime(PLUGIN_OPERATION_STATE_CHANGED, (payload) => {
|
|
880
|
+
const event = asStateChanged(payload);
|
|
881
|
+
if (!parentEntityId || event == null || event.parentEntityId !== parentEntityId || !hasParentEntityType(event, parentEntityType)) {
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
queryClient.setQueryData(
|
|
885
|
+
pluginOperationKeys.byParent(parentEntityType, parentEntityId),
|
|
886
|
+
(current) => mergeIntoList(current, event)
|
|
887
|
+
);
|
|
888
|
+
});
|
|
889
|
+
return query;
|
|
890
|
+
}
|
|
891
|
+
function useLatestTerminalOperationByParent(parentEntityType, parentEntityId) {
|
|
892
|
+
const queryClient = reactQuery.useQueryClient();
|
|
893
|
+
const { invoke } = extensionRuntime.useMcpTool(
|
|
894
|
+
PLUGIN_OPERATION_TOOLS.latestTerminalByParent
|
|
895
|
+
);
|
|
896
|
+
const key = pluginOperationKeys.latestTerminalByParent(parentEntityType, parentEntityId ?? "");
|
|
897
|
+
const query = reactQuery.useQuery({
|
|
898
|
+
queryKey: key,
|
|
899
|
+
enabled: Boolean(parentEntityId),
|
|
900
|
+
queryFn: async () => (await invoke({ parentEntityType, parentEntityId }))?.item ?? null
|
|
901
|
+
});
|
|
902
|
+
usePluginRealtime(PLUGIN_OPERATION_STATE_CHANGED, (payload) => {
|
|
903
|
+
const event = asStateChanged(payload);
|
|
904
|
+
if (parentEntityId && event != null && event.parentEntityId === parentEntityId && hasParentEntityType(event, parentEntityType) && isTerminalOperationStatus(event.status)) {
|
|
905
|
+
void queryClient.invalidateQueries({ queryKey: key });
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
return query;
|
|
909
|
+
}
|
|
769
910
|
var DEFAULT_MAX_UPLOAD_BYTES = 30 * 1024 * 1024;
|
|
770
911
|
function useMcpUpload(opts) {
|
|
771
912
|
const transport = extensionRuntime.useExtensionRuntimeTransport(opts?.transport);
|
|
@@ -1282,9 +1423,12 @@ exports.HOST_CHROME_CONTRACT_VERSION = HOST_CHROME_CONTRACT_VERSION;
|
|
|
1282
1423
|
exports.HostSidebarActionsContext = HostSidebarActionsContext;
|
|
1283
1424
|
exports.LIST_CURRENCIES_TOOL = LIST_CURRENCIES_TOOL;
|
|
1284
1425
|
exports.MissingViewFallback = MissingViewFallback;
|
|
1426
|
+
exports.OPERATION_FALLBACK_POLL_MS = OPERATION_FALLBACK_POLL_MS;
|
|
1285
1427
|
exports.ORGANISATION_SETTINGS_URI = ORGANISATION_SETTINGS_URI;
|
|
1286
1428
|
exports.OVERLAY_HOST_CONTRACT_VERSION = OVERLAY_HOST_CONTRACT_VERSION;
|
|
1287
1429
|
exports.OverlayHostContext = OverlayHostContext;
|
|
1430
|
+
exports.PLUGIN_OPERATION_STATE_CHANGED = PLUGIN_OPERATION_STATE_CHANGED;
|
|
1431
|
+
exports.PLUGIN_OPERATION_TOOLS = PLUGIN_OPERATION_TOOLS;
|
|
1288
1432
|
exports.PluginPortalScope = PluginPortalScope;
|
|
1289
1433
|
exports.PluginStyleScope = PluginStyleScope;
|
|
1290
1434
|
exports.REPORTING_CURRENCY_TOOL = REPORTING_CURRENCY_TOOL2;
|
|
@@ -1301,13 +1445,17 @@ exports.createUseView = createUseView;
|
|
|
1301
1445
|
exports.definePlatformReactPluginOverlay = definePlatformReactPluginOverlay;
|
|
1302
1446
|
exports.definePlatformReactPluginPage = definePlatformReactPluginPage;
|
|
1303
1447
|
exports.deriveHostEntityToken = deriveHostEntityToken;
|
|
1448
|
+
exports.hasKind = hasKind;
|
|
1449
|
+
exports.hasParentEntityType = hasParentEntityType;
|
|
1304
1450
|
exports.injectPluginStyles = injectPluginStyles;
|
|
1305
1451
|
exports.isComponent = isComponent;
|
|
1306
1452
|
exports.isHostChromeCompatible = isHostChromeCompatible;
|
|
1453
|
+
exports.isTerminalOperationStatus = isTerminalOperationStatus;
|
|
1307
1454
|
exports.mcpTool = mcpTool;
|
|
1308
1455
|
exports.menuConfigToHostSidebarInput = menuConfigToHostSidebarInput;
|
|
1309
1456
|
exports.normaliseSlug = normaliseSlug;
|
|
1310
1457
|
exports.notViaMcp = notViaMcp;
|
|
1458
|
+
exports.pluginOperationKeys = pluginOperationKeys;
|
|
1311
1459
|
exports.reportHostChromeDiagnostic = reportHostChromeDiagnostic;
|
|
1312
1460
|
exports.resolveActiveNavHref = resolveActiveNavHref;
|
|
1313
1461
|
exports.resolveSurfaceBase = resolveSurfaceBase;
|
|
@@ -1316,10 +1464,13 @@ exports.surfacePathFor = surfacePathFor;
|
|
|
1316
1464
|
exports.toHostSidebarInput = toHostSidebarInput;
|
|
1317
1465
|
exports.useAuthenticatedQueries = useAuthenticatedQueries;
|
|
1318
1466
|
exports.useAuthenticatedQuery = useAuthenticatedQuery;
|
|
1467
|
+
exports.useBackgroundOperation = useBackgroundOperation;
|
|
1319
1468
|
exports.useCurrency = useCurrency;
|
|
1320
1469
|
exports.useHostSidebarActions = useHostSidebarActions;
|
|
1470
|
+
exports.useLatestTerminalOperationByParent = useLatestTerminalOperationByParent;
|
|
1321
1471
|
exports.useManagedLifecycle = useManagedLifecycle;
|
|
1322
1472
|
exports.useMcpUpload = useMcpUpload;
|
|
1473
|
+
exports.useOperationsByParent = useOperationsByParent;
|
|
1323
1474
|
exports.useOrgFormatSync = useOrgFormatSync;
|
|
1324
1475
|
exports.useOverlayHost = useOverlayHost;
|
|
1325
1476
|
exports.usePluginRealtime = usePluginRealtime;
|