@modcore/plugin-ui-sdk 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+
5
+ - Initial public iframe-bridge types, constrained client, UI binding declaration, accessibility contract, and deterministic mock host.
package/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # `@modcore/plugin-ui-sdk`
2
+
3
+ Framework-independent public SDK for a ModCore plugin UI. It is designed for the sandboxed iframe bridge and deliberately does not expose Vue, Router, Pinia, browser cookies, tokens, raw `fetch`, arbitrary URLs, or host-private modules.
4
+
5
+ ## Support contract
6
+
7
+ - License: Apache-2.0
8
+ - Protocol: `modcore.ui.bridge/v1`
9
+ - Supported host range: `>=0.1.0 <0.2.0`
10
+ - Node: `>=22.12.0`; package manager: pnpm `10.32.1`
11
+ - Deprecation window: at least one complete SDK minor release
12
+ - Security reports: <https://modcore.quatbyte.com/security>
13
+
14
+ The built `dist/release-metadata.json` contains the exact source revision, protocol range, integrity-algorithm location, deprecation window, and security channel. Package-manager registry metadata provides the release tarball SHA-512 integrity value.
15
+
16
+ ## Usage
17
+
18
+ ```ts
19
+ import { createPluginUiClient, defineUiBinding } from "@modcore/plugin-ui-sdk";
20
+ import { createMockUiHost } from "@modcore/plugin-ui-sdk/testing";
21
+ ```
22
+
23
+ Use `defineUiBinding()` for a `UI_ONLY` theme’s explicit target contract. `createPluginUiClient()` accepts only the authenticated host bridge transport; it has no API for URLs, authorization headers, cookies, or raw network clients. Use `createMockUiHost()` for local tests without a ModCore checkout, management token, or production host.
24
+
25
+ ## Release evidence
26
+
27
+ Before a public release, run `pnpm test`, `pnpm test:types`, `pnpm build`, and `pnpm pack:check`; publish the generated package metadata, registry integrity value, source revision, changelog, and this support contract together. This source checkout does not publish to a registry automatically.
package/SECURITY.md ADDED
@@ -0,0 +1,5 @@
1
+ # Security policy
2
+
3
+ Report SDK vulnerabilities through <https://modcore.quatbyte.com/security>. Do not include tokens, cookies, customer data, or exploit payloads in public issues.
4
+
5
+ The SDK never accepts arbitrary URLs, authorization headers, browser cookies, or raw `fetch` implementations. Hosts must still enforce all bridge authorization, tenant, rate, timeout, audit, and lifecycle checks.
@@ -0,0 +1,27 @@
1
+ import { type UiAccessibilityDescriptor, type UiBinding, type UiBootstrapContext, type UiBridgeTransport, type UiContract, type UiLocalizer, type UiMessageCatalog, type UiTelemetryEvent } from "./types.js";
2
+ export { BRIDGE_PROTOCOL } from "./types.js";
3
+ export type * from "./types.js";
4
+ /** Defines a static target binding without granting arbitrary HTTP or host access. */
5
+ export declare function defineUiBinding<TContract extends UiContract>(binding: UiBinding<TContract>): UiBinding<TContract>;
6
+ /** Rejects descriptors that cannot make the iframe boundary accessible to keyboard and AT users. */
7
+ export declare function defineUiAccessibility(descriptor: UiAccessibilityDescriptor): UiAccessibilityDescriptor;
8
+ /**
9
+ * Creates an isolated plugin-local translator. Host locale changes remain observable through the
10
+ * bridge client, while plugins retain ownership of their namespaced message catalogs.
11
+ */
12
+ export declare function createUiLocalizer(locale: string, messages: UiMessageCatalog): UiLocalizer;
13
+ export interface PluginUiClient<TContract extends UiContract> {
14
+ readonly context: UiBootstrapContext;
15
+ request<TOperationId extends keyof TContract["operations"] & string>(operationId: TOperationId, request: TContract["operations"][TOperationId]["request"]): Promise<TContract["operations"][TOperationId]["response"]>;
16
+ navigate(navigationId: string): Promise<void>;
17
+ telemetry(event: UiTelemetryEvent): Promise<void>;
18
+ onLocaleChange(listener: (locale: string) => void): () => void;
19
+ onThemeChange(listener: (tokens: Readonly<Record<string, string>>) => void): () => void;
20
+ dispose(): Promise<void>;
21
+ }
22
+ /**
23
+ * Creates a narrow client for an already-authenticated MessagePort bridge. The SDK intentionally
24
+ * accepts no URL, token, cookie, header, raw fetch implementation, Router, or framework object.
25
+ */
26
+ export declare function createPluginUiClient<TContract extends UiContract>(context: UiBootstrapContext, transport: UiBridgeTransport<TContract>): PluginUiClient<TContract>;
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACtB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,mBAAmB,YAAY,CAAC;AAEhC,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,SAAS,SAAS,UAAU,EAAE,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC,SAAS,CAAC,CAQjH;AAED,oGAAoG;AACpG,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,yBAAyB,GAAG,yBAAyB,CAatG;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,WAAW,CAYzF;AAED,MAAM,WAAW,cAAc,CAAC,SAAS,SAAS,UAAU;IAC1D,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,OAAO,CAAC,YAAY,SAAS,MAAM,SAAS,CAAC,YAAY,CAAC,GAAG,MAAM,EACjE,WAAW,EAAE,YAAY,EACzB,OAAO,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,GACxD,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IAC9D,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,SAAS,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,cAAc,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC/D,aAAa,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACxF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,SAAS,UAAU,EAC/D,OAAO,EAAE,kBAAkB,EAC3B,SAAS,EAAE,iBAAiB,CAAC,SAAS,CAAC,GACtC,cAAc,CAAC,SAAS,CAAC,CA0C3B"}
package/dist/index.js ADDED
@@ -0,0 +1,89 @@
1
+ import { BRIDGE_PROTOCOL, } from "./types.js";
2
+ export { BRIDGE_PROTOCOL } from "./types.js";
3
+ /** Defines a static target binding without granting arbitrary HTTP or host access. */
4
+ export function defineUiBinding(binding) {
5
+ if (!binding.id || !binding.targetPluginInstanceId || !binding.targetSurfaceId) {
6
+ throw new Error("A UI binding requires stable IDs for itself and its target surface.");
7
+ }
8
+ if (!binding.uiContract.id || !binding.uiContract.version || !/^[a-f0-9]{64}$/.test(binding.uiContract.schemaSha256)) {
9
+ throw new Error("A UI binding requires a versioned contract with a SHA-256 schema digest.");
10
+ }
11
+ return Object.freeze({ ...binding, uiContract: Object.freeze({ ...binding.uiContract }) });
12
+ }
13
+ /** Rejects descriptors that cannot make the iframe boundary accessible to keyboard and AT users. */
14
+ export function defineUiAccessibility(descriptor) {
15
+ if (!descriptor.localizedIframeTitle.trim()) {
16
+ throw new Error("A plugin UI requires a localized iframe title.");
17
+ }
18
+ if (!descriptor.supportsKeyboardReturn ||
19
+ !descriptor.supportsReducedMotion ||
20
+ !descriptor.supportsUserColors ||
21
+ !descriptor.supportsTextZoom) {
22
+ throw new Error("A plugin UI must support keyboard return, reduced motion, user colors, and text zoom.");
23
+ }
24
+ return Object.freeze({ ...descriptor });
25
+ }
26
+ /**
27
+ * Creates an isolated plugin-local translator. Host locale changes remain observable through the
28
+ * bridge client, while plugins retain ownership of their namespaced message catalogs.
29
+ */
30
+ export function createUiLocalizer(locale, messages) {
31
+ if (!locale.trim())
32
+ throw new Error("A plugin UI localizer requires a locale.");
33
+ return Object.freeze({
34
+ locale,
35
+ t(key, parameters = {}) {
36
+ const template = messages[key];
37
+ if (!template)
38
+ return key;
39
+ return template.replace(/\{([a-zA-Z][a-zA-Z0-9_.-]*)\}/g, (placeholder, name) => Object.hasOwn(parameters, name) ? String(parameters[name]) : placeholder);
40
+ },
41
+ });
42
+ }
43
+ /**
44
+ * Creates a narrow client for an already-authenticated MessagePort bridge. The SDK intentionally
45
+ * accepts no URL, token, cookie, header, raw fetch implementation, Router, or framework object.
46
+ */
47
+ export function createPluginUiClient(context, transport) {
48
+ if (context.protocol !== BRIDGE_PROTOCOL || context.policyGeneration < 1) {
49
+ throw new Error("The host supplied an unsupported UI bridge context.");
50
+ }
51
+ let disposed = false;
52
+ const requireActive = () => {
53
+ if (disposed)
54
+ throw new Error("The plugin UI bridge has been disposed.");
55
+ };
56
+ return Object.freeze({
57
+ context: Object.freeze({ ...context, themeTokens: Object.freeze({ ...context.themeTokens }) }),
58
+ async request(operationId, request) {
59
+ requireActive();
60
+ return transport.request(operationId, request);
61
+ },
62
+ async navigate(navigationId) {
63
+ requireActive();
64
+ if (!context.allowedNavigationIds.includes(navigationId)) {
65
+ throw new Error("Navigation target is not authorized by the host.");
66
+ }
67
+ await transport.navigate(navigationId);
68
+ },
69
+ async telemetry(event) {
70
+ requireActive();
71
+ await transport.telemetry(event);
72
+ },
73
+ onLocaleChange(listener) {
74
+ requireActive();
75
+ return transport.onLocaleChange(listener);
76
+ },
77
+ onThemeChange(listener) {
78
+ requireActive();
79
+ return transport.onThemeChange(listener);
80
+ },
81
+ async dispose() {
82
+ if (disposed)
83
+ return;
84
+ disposed = true;
85
+ await transport.dispose();
86
+ },
87
+ });
88
+ }
89
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,GAShB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG7C,sFAAsF;AACtF,MAAM,UAAU,eAAe,CAA+B,OAA6B;IACzF,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,sBAAsB,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;QAC/E,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACrH,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;IAC9F,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;AAC7F,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,qBAAqB,CAAC,UAAqC;IACzE,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IACD,IACE,CAAC,UAAU,CAAC,sBAAsB;QAClC,CAAC,UAAU,CAAC,qBAAqB;QACjC,CAAC,UAAU,CAAC,kBAAkB;QAC9B,CAAC,UAAU,CAAC,gBAAgB,EAC5B,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uFAAuF,CAAC,CAAC;IAC3G,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,QAA0B;IAC1E,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAChF,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,MAAM;QACN,CAAC,CAAC,GAAW,EAAE,aAAwD,EAAE;YACvE,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO,GAAG,CAAC;YAC1B,OAAO,QAAQ,CAAC,OAAO,CAAC,gCAAgC,EAAE,CAAC,WAAW,EAAE,IAAY,EAAE,EAAE,CACtF,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CACzE,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAeD;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAA2B,EAC3B,SAAuC;IAEvC,IAAI,OAAO,CAAC,QAAQ,KAAK,eAAe,IAAI,OAAO,CAAC,gBAAgB,GAAG,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,aAAa,GAAG,GAAS,EAAE;QAC/B,IAAI,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC3E,CAAC,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QAC9F,KAAK,CAAC,OAAO,CACX,WAAyB,EACzB,OAAyD;YAEzD,aAAa,EAAE,CAAC;YAChB,OAAO,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,YAAoB;YACjC,aAAa,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBACzD,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;YACtE,CAAC;YACD,MAAM,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QACzC,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,KAAuB;YACrC,aAAa,EAAE,CAAC;YAChB,MAAM,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QACD,cAAc,CAAC,QAAkC;YAC/C,aAAa,EAAE,CAAC;YAChB,OAAO,SAAS,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;QACD,aAAa,CAAC,QAA4D;YACxE,aAAa,EAAE,CAAC;YAChB,OAAO,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC3C,CAAC;QACD,KAAK,CAAC,OAAO;YACX,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC;QAC5B,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,14 @@
1
+ {
2
+ "license": "Apache-2.0",
3
+ "sourceRevision": "86fb0c51b0de6734dd9fe1dedb2f7d03b1727b78",
4
+ "protocols": [
5
+ "modcore.ui.bridge/v1"
6
+ ],
7
+ "supportedHostVersions": ">=0.1.0 <0.2.0",
8
+ "integrity": {
9
+ "algorithm": "sha512",
10
+ "location": "package-manager registry metadata"
11
+ },
12
+ "deprecationWindow": "At least one complete SDK minor release.",
13
+ "securityDisclosure": "https://modcore.quatbyte.com/security"
14
+ }
@@ -0,0 +1,16 @@
1
+ import { type UiBootstrapContext, type UiBridgeTransport, type UiContract } from "./types.js";
2
+ export interface MockUiHost<TContract extends UiContract> {
3
+ readonly context: UiBootstrapContext;
4
+ readonly transport: UiBridgeTransport<TContract>;
5
+ readonly calls: readonly {
6
+ readonly kind: string;
7
+ readonly value: unknown;
8
+ }[];
9
+ setLocale(locale: string): void;
10
+ setTheme(tokens: Readonly<Record<string, string>>): void;
11
+ }
12
+ /** A deterministic local host for SDK tests; it exposes only operations declared by the contract. */
13
+ export declare function createMockUiHost<TContract extends UiContract>(contract: TContract, responses: Partial<{
14
+ [K in keyof TContract["operations"] & string]: TContract["operations"][K]["response"];
15
+ }>, context: Omit<UiBootstrapContext, "protocol">): MockUiHost<TContract>;
16
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,UAAU,EAAyB,MAAM,YAAY,CAAC;AAEtI,MAAM,WAAW,UAAU,CAAC,SAAS,SAAS,UAAU;IACtD,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACjD,QAAQ,CAAC,KAAK,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC9E,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;CAC1D;AAED,qGAAqG;AACrG,wBAAgB,gBAAgB,CAAC,SAAS,SAAS,UAAU,EAC3D,QAAQ,EAAE,SAAS,EACnB,SAAS,EAAE,OAAO,CAAC;KAAG,CAAC,IAAI,MAAM,SAAS,CAAC,YAAY,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;CAAE,CAAC,EAC7G,OAAO,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC,GAC5C,UAAU,CAAC,SAAS,CAAC,CAiDvB"}
@@ -0,0 +1,54 @@
1
+ import { BRIDGE_PROTOCOL } from "./types.js";
2
+ /** A deterministic local host for SDK tests; it exposes only operations declared by the contract. */
3
+ export function createMockUiHost(contract, responses, context) {
4
+ const calls = [];
5
+ const localeListeners = new Set();
6
+ const themeListeners = new Set();
7
+ let disposed = false;
8
+ const requireActive = () => {
9
+ if (disposed)
10
+ throw new Error("Mock UI host is disposed.");
11
+ };
12
+ const transport = {
13
+ async request(operationId, request) {
14
+ requireActive();
15
+ if (!(operationId in contract.operations) || !(operationId in responses)) {
16
+ throw new Error("Mock host rejected an undeclared or unconfigured operation.");
17
+ }
18
+ calls.push({ kind: "request", value: { operationId, request } });
19
+ return responses[operationId];
20
+ },
21
+ async navigate(navigationId) {
22
+ requireActive();
23
+ calls.push({ kind: "navigate", value: navigationId });
24
+ },
25
+ async telemetry(event) {
26
+ requireActive();
27
+ calls.push({ kind: "telemetry", value: event });
28
+ },
29
+ async dispose() {
30
+ disposed = true;
31
+ calls.push({ kind: "dispose", value: null });
32
+ },
33
+ onLocaleChange(listener) {
34
+ localeListeners.add(listener);
35
+ return () => localeListeners.delete(listener);
36
+ },
37
+ onThemeChange(listener) {
38
+ themeListeners.add(listener);
39
+ return () => themeListeners.delete(listener);
40
+ },
41
+ };
42
+ return {
43
+ context: Object.freeze({ ...context, protocol: BRIDGE_PROTOCOL }),
44
+ transport,
45
+ calls,
46
+ setLocale(locale) {
47
+ localeListeners.forEach((listener) => listener(locale));
48
+ },
49
+ setTheme(tokens) {
50
+ themeListeners.forEach((listener) => listener(tokens));
51
+ },
52
+ };
53
+ }
54
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAA2F,MAAM,YAAY,CAAC;AAUtI,qGAAqG;AACrG,MAAM,UAAU,gBAAgB,CAC9B,QAAmB,EACnB,SAA6G,EAC7G,OAA6C;IAE7C,MAAM,KAAK,GAAuC,EAAE,CAAC;IACrD,MAAM,eAAe,GAAG,IAAI,GAAG,EAA4B,CAAC;IAC5D,MAAM,cAAc,GAAG,IAAI,GAAG,EAAsD,CAAC;IACrF,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,aAAa,GAAG,GAAS,EAAE;QAC/B,IAAI,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC7D,CAAC,CAAC;IACF,MAAM,SAAS,GAAiC;QAC9C,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO;YAChC,aAAa,EAAE,CAAC;YAChB,IAAI,CAAC,CAAC,WAAW,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,WAAW,IAAI,SAAS,CAAC,EAAE,CAAC;gBACzE,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;YACjF,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;YACjE,OAAO,SAAS,CAAC,WAAW,CAA4D,CAAC;QAC3F,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,YAAY;YACzB,aAAa,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,KAAuB;YACrC,aAAa,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,KAAK,CAAC,OAAO;YACX,QAAQ,GAAG,IAAI,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,cAAc,CAAC,QAAQ;YACrB,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC9B,OAAO,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChD,CAAC;QACD,aAAa,CAAC,QAAQ;YACpB,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC7B,OAAO,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC/C,CAAC;KACF,CAAC;IACF,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;QACjE,SAAS;QACT,KAAK;QACL,SAAS,CAAC,MAAM;YACd,eAAe,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1D,CAAC;QACD,QAAQ,CAAC,MAAM;YACb,cAAc,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACzD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,64 @@
1
+ /** Stable types for the framework-independent ModCore UI bridge. */
2
+ export declare const BRIDGE_PROTOCOL: "modcore.ui.bridge/v1";
3
+ export type BridgeProtocol = typeof BRIDGE_PROTOCOL;
4
+ export interface UiCandidateIdentity {
5
+ readonly providerPluginInstanceId: string;
6
+ readonly providerPluginId: string;
7
+ readonly artifactSha256: string;
8
+ readonly uiId: string;
9
+ readonly bindingId?: string;
10
+ }
11
+ export interface UiBootstrapContext {
12
+ readonly protocol: BridgeProtocol;
13
+ readonly candidate: UiCandidateIdentity;
14
+ readonly surfaceId: string;
15
+ readonly policyGeneration: number;
16
+ readonly locale: string;
17
+ readonly themeTokens: Readonly<Record<string, string>>;
18
+ readonly allowedNavigationIds: readonly string[];
19
+ }
20
+ export interface UiContractOperation<TRequest = unknown, TResponse = unknown> {
21
+ readonly id: string;
22
+ readonly request: TRequest;
23
+ readonly response: TResponse;
24
+ readonly access: "read" | "write";
25
+ }
26
+ export interface UiContract<TOperation extends UiContractOperation = UiContractOperation> {
27
+ readonly id: string;
28
+ readonly version: string;
29
+ readonly schemaSha256: string;
30
+ readonly operations: Readonly<Record<string, TOperation>>;
31
+ }
32
+ export interface UiBinding<TContract extends UiContract = UiContract> {
33
+ readonly id: string;
34
+ readonly targetPluginInstanceId: string;
35
+ readonly targetSurfaceId: string;
36
+ readonly uiContract: Pick<TContract, "id" | "version" | "schemaSha256">;
37
+ }
38
+ export interface UiTelemetryEvent {
39
+ readonly name: string;
40
+ readonly numericValues?: Readonly<Record<string, number>>;
41
+ readonly reviewedLabels?: Readonly<Record<string, string>>;
42
+ }
43
+ export interface UiAccessibilityDescriptor {
44
+ readonly localizedIframeTitle: string;
45
+ readonly statusRole: "status" | "alert";
46
+ readonly supportsKeyboardReturn: true;
47
+ readonly supportsReducedMotion: true;
48
+ readonly supportsUserColors: true;
49
+ readonly supportsTextZoom: true;
50
+ }
51
+ export type UiMessageCatalog = Readonly<Record<string, string>>;
52
+ export interface UiLocalizer {
53
+ readonly locale: string;
54
+ t(key: string, parameters?: Readonly<Record<string, string | number>>): string;
55
+ }
56
+ export interface UiBridgeTransport<TContract extends UiContract = UiContract> {
57
+ request<TOperationId extends keyof TContract["operations"] & string>(operationId: TOperationId, request: TContract["operations"][TOperationId]["request"]): Promise<TContract["operations"][TOperationId]["response"]>;
58
+ navigate(navigationId: string): Promise<void>;
59
+ telemetry(event: UiTelemetryEvent): Promise<void>;
60
+ dispose(): Promise<void>;
61
+ onLocaleChange(listener: (locale: string) => void): () => void;
62
+ onThemeChange(listener: (tokens: Readonly<Record<string, string>>) => void): () => void;
63
+ }
64
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ /** Stable types for the framework-independent ModCore UI bridge. */
2
+ export const BRIDGE_PROTOCOL = "modcore.ui.bridge/v1";
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,MAAM,CAAC,MAAM,eAAe,GAAG,sBAA+B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@modcore/plugin-ui-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Public, framework-independent UI bridge SDK for ModCore plugins.",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "packageManager": "pnpm@10.32.1",
8
+ "engines": {
9
+ "node": ">=22.12.0"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ },
16
+ "./types": {
17
+ "types": "./dist/types.d.ts",
18
+ "import": "./dist/types.js"
19
+ },
20
+ "./testing": {
21
+ "types": "./dist/testing.d.ts",
22
+ "import": "./dist/testing.js"
23
+ },
24
+ "./package.json": "./package.json"
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "README.md",
29
+ "CHANGELOG.md",
30
+ "SECURITY.md"
31
+ ],
32
+ "scripts": {
33
+ "clean": "node ./scripts/clean.mjs",
34
+ "build": "pnpm run clean && tsc -p tsconfig.build.json && node ./scripts/write-release-metadata.mjs",
35
+ "typecheck": "tsc -p tsconfig.json --noEmit",
36
+ "test": "pnpm run build && node --test test/**/*.test.mjs",
37
+ "test:types": "tsc -p tsconfig.test.json --noEmit",
38
+ "pack:check": "pnpm pack --pack-destination .artifacts"
39
+ },
40
+ "devDependencies": {
41
+ "typescript": "^5.8.3"
42
+ },
43
+ "modcore": {
44
+ "protocol": "modcore.ui.bridge/v1",
45
+ "supportedHostVersions": ">=0.1.0 <0.2.0",
46
+ "sourceRevision": "generated-at-build",
47
+ "deprecationWindow": "At least one complete SDK minor release.",
48
+ "securityDisclosure": "https://modcore.quatbyte.com/security"
49
+ }
50
+ }