@qontinui/ui-bridge-native 0.1.4 → 0.1.6
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/dist/control/{index.d.mts → action-executor.d.ts} +6 -10
- package/dist/control/action-executor.d.ts.map +1 -0
- package/dist/control/index.d.ts +5 -91
- package/dist/control/index.d.ts.map +1 -0
- package/dist/control/index.js +1 -1
- package/dist/control/index.js.map +1 -1
- package/dist/control/index.mjs +1 -1
- package/dist/control/index.mjs.map +1 -1
- package/dist/{types-BCYWwyVy.d.ts → control/types.d.ts} +17 -18
- package/dist/control/types.d.ts.map +1 -0
- package/dist/core/element-identifier.d.ts +41 -0
- package/dist/core/element-identifier.d.ts.map +1 -0
- package/dist/core/index.d.ts +6 -43
- package/dist/core/index.d.ts.map +1 -0
- package/dist/{registry-B8A_EoxS.d.ts → core/registry.d.ts} +10 -13
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/{types-BPNuYxDx.d.ts → core/types.d.ts} +30 -30
- package/dist/core/types.d.ts.map +1 -0
- package/dist/debug/index.d.ts +4 -44
- package/dist/debug/index.d.ts.map +1 -0
- package/dist/debug/index.js.map +1 -1
- package/dist/debug/index.mjs.map +1 -1
- package/dist/debug/{index.d.mts → inspector.d.ts} +3 -6
- package/dist/debug/inspector.d.ts.map +1 -0
- package/dist/design/{index.d.mts → design-inspector-native.d.ts} +7 -11
- package/dist/design/design-inspector-native.d.ts.map +1 -0
- package/dist/{design-types-BHr6Q1FX.d.ts → design/design-types.d.ts} +10 -11
- package/dist/design/design-types.d.ts.map +1 -0
- package/dist/design/index.d.ts +5 -60
- package/dist/design/index.d.ts.map +1 -0
- package/dist/index.d.ts +28 -73
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +129 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +129 -23
- package/dist/index.mjs.map +1 -1
- package/dist/react/UIBridgeNativeProvider.d.ts +147 -0
- package/dist/react/UIBridgeNativeProvider.d.ts.map +1 -0
- package/dist/react/index.d.ts +8 -69
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +138 -23
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +138 -23
- package/dist/react/index.mjs.map +1 -1
- package/dist/react/{index.d.mts → useAutoRegister.d.ts} +7 -15
- package/dist/react/useAutoRegister.d.ts.map +1 -0
- package/dist/react/useUIBridge.d.ts +103 -0
- package/dist/react/useUIBridge.d.ts.map +1 -0
- package/dist/react/useUIComponent.d.ts +112 -0
- package/dist/react/useUIComponent.d.ts.map +1 -0
- package/dist/react/useUIElement.d.ts +162 -0
- package/dist/react/useUIElement.d.ts.map +1 -0
- package/dist/server/design-handlers.d.ts +47 -0
- package/dist/server/design-handlers.d.ts.map +1 -0
- package/dist/server/handlers.d.ts +20 -0
- package/dist/server/handlers.d.ts.map +1 -0
- package/dist/server/http-server.d.ts +247 -0
- package/dist/server/http-server.d.ts.map +1 -0
- package/dist/server/index.d.ts +13 -117
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +102 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +102 -1
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/types.d.ts +200 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/ws-connection.d.ts +48 -0
- package/dist/server/ws-connection.d.ts.map +1 -0
- package/dist/server/ws-event-bridge.d.ts +113 -0
- package/dist/server/ws-event-bridge.d.ts.map +1 -0
- package/dist/server/ws-protocol.d.ts +48 -0
- package/dist/server/ws-protocol.d.ts.map +1 -0
- package/dist/server/ws-types.d.ts +65 -0
- package/dist/server/ws-types.d.ts.map +1 -0
- package/dist/transport/CloudRelayClient.d.ts +51 -0
- package/dist/transport/CloudRelayClient.d.ts.map +1 -0
- package/dist/transport/DeviceAnnouncer.d.ts +75 -0
- package/dist/transport/DeviceAnnouncer.d.ts.map +1 -0
- package/dist/transport/index.d.ts +3 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/core/index.d.mts +0 -46
- package/dist/design-types-BHr6Q1FX.d.mts +0 -205
- package/dist/http-server-B7KudcYJ.d.ts +0 -622
- package/dist/http-server-D7uVANBU.d.mts +0 -622
- package/dist/index.d.mts +0 -76
- package/dist/registry-DhbGbl9c.d.mts +0 -215
- package/dist/server/index.d.mts +0 -119
- package/dist/types-BPNuYxDx.d.mts +0 -383
- package/dist/types-Bcj7ji97.d.mts +0 -177
- package/dist/useUIBridge-CDZbWxII.d.ts +0 -571
- package/dist/useUIBridge-DfIEq9EQ.d.mts +0 -571
package/dist/react/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createContext, useRef, useState, useCallback, useEffect, useMemo, useContext } from 'react';
|
|
2
|
+
import { StyleSheet, Platform } from 'react-native';
|
|
2
3
|
import { jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { StyleSheet } from 'react-native';
|
|
4
4
|
|
|
5
5
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
6
6
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
@@ -687,7 +687,7 @@ var DefaultNativeActionExecutor = class {
|
|
|
687
687
|
if (!params?.text) {
|
|
688
688
|
throw new Error("Type action requires text parameter");
|
|
689
689
|
}
|
|
690
|
-
if (params.clearFirst) {
|
|
690
|
+
if (params.clearFirst || params.clear) {
|
|
691
691
|
await this.performClear(element, props);
|
|
692
692
|
}
|
|
693
693
|
if (params.delay && params.delay > 0) {
|
|
@@ -1873,6 +1873,15 @@ function createServerHandlers(registry, executor, config) {
|
|
|
1873
1873
|
timestamp: Date.now(),
|
|
1874
1874
|
...stats
|
|
1875
1875
|
};
|
|
1876
|
+
if (config?.appInfo) {
|
|
1877
|
+
response.uiBridge = {
|
|
1878
|
+
version: "0.3.0",
|
|
1879
|
+
...config.appInfo,
|
|
1880
|
+
capabilities: ["elements", "components", "actions", "design"],
|
|
1881
|
+
elementCount: stats.elements,
|
|
1882
|
+
componentCount: stats.components
|
|
1883
|
+
};
|
|
1884
|
+
}
|
|
1876
1885
|
return success2(response);
|
|
1877
1886
|
}
|
|
1878
1887
|
};
|
|
@@ -1911,6 +1920,10 @@ var WS_ROUTES = [
|
|
|
1911
1920
|
{ pattern: "health", handler: "health", httpMethods: ["GET"] },
|
|
1912
1921
|
// Elements
|
|
1913
1922
|
{ pattern: "control/elements", handler: "getElements", httpMethods: ["GET"] },
|
|
1923
|
+
// Flat alias — matches the runner UI Bridge's `/ui-bridge/elements` path so
|
|
1924
|
+
// agents can use the same URL across runner + mobile without remembering
|
|
1925
|
+
// the `control/` prefix. Delegates to the same handler.
|
|
1926
|
+
{ pattern: "elements", handler: "getElements", httpMethods: ["GET"] },
|
|
1914
1927
|
{ pattern: "control/element/:id", handler: "getElement", httpMethods: ["GET"] },
|
|
1915
1928
|
{ pattern: "control/element/:id/state", handler: "getElementState", httpMethods: ["GET"] },
|
|
1916
1929
|
{ pattern: "control/element/:id/action", handler: "executeAction", httpMethods: ["POST"] },
|
|
@@ -1961,6 +1974,87 @@ var WS_ROUTES = [
|
|
|
1961
1974
|
// Meta / Introspection
|
|
1962
1975
|
{ pattern: "meta/methods", handler: "getMethods", httpMethods: ["GET"] }
|
|
1963
1976
|
];
|
|
1977
|
+
var HANDLER_DESCRIPTIONS = {
|
|
1978
|
+
health: "Liveness probe; returns app metadata + element count",
|
|
1979
|
+
getElements: "Flat list of registered UI elements",
|
|
1980
|
+
getElement: "Single element by id",
|
|
1981
|
+
getElementState: "Dynamic state (value, focused, checked) for one element",
|
|
1982
|
+
executeAction: 'Run an action on an element (see "actions" below for names)',
|
|
1983
|
+
getComponents: "Higher-level components with action schemas",
|
|
1984
|
+
getComponent: "Component detail + per-action paramSchema",
|
|
1985
|
+
executeComponentAction: "Invoke a component action directly (preferred over button clicks)",
|
|
1986
|
+
find: "AI-powered element search by natural-language query",
|
|
1987
|
+
getSnapshot: "Full snapshot: elements + route + state. Supports ?visibleOnly=true and ?currentRouteOnly=true",
|
|
1988
|
+
getWorkflows: "List registered workflows",
|
|
1989
|
+
runWorkflow: "Trigger a workflow by id",
|
|
1990
|
+
pageRefresh: "Reload the current route",
|
|
1991
|
+
pageNavigate: "Imperative router.push(url) \u2014 preferred over tapping tab buttons",
|
|
1992
|
+
pageReplace: "router.replace(url)",
|
|
1993
|
+
pageGoBack: "router.back()",
|
|
1994
|
+
pageGoForward: "router.forward()",
|
|
1995
|
+
getScreenshot: "PNG screenshot of the current screen",
|
|
1996
|
+
getElementStyles: "Computed styles for an element (design review)",
|
|
1997
|
+
getElementStateStyles: "Computed styles per interaction state (hover/focus/disabled)",
|
|
1998
|
+
getDesignSnapshot: "Visual + style snapshot for design review",
|
|
1999
|
+
getResponsiveSnapshots: "Screenshots at multiple viewport widths",
|
|
2000
|
+
runDesignAudit: "Accessibility + visual audit",
|
|
2001
|
+
loadStyleGuide: "Load a design system style guide",
|
|
2002
|
+
getStyleGuide: "Fetch the currently loaded style guide",
|
|
2003
|
+
clearStyleGuide: "Unload the style guide",
|
|
2004
|
+
evaluateQuality: "Score the current UI against a quality context",
|
|
2005
|
+
getQualityContexts: "List available quality evaluation contexts",
|
|
2006
|
+
saveBaseline: "Save a quality baseline snapshot",
|
|
2007
|
+
diffBaseline: "Diff current UI against a saved baseline",
|
|
2008
|
+
getMethods: "List every handler name (legacy introspection)"
|
|
2009
|
+
};
|
|
2010
|
+
var ACTION_REFERENCE = [
|
|
2011
|
+
{ name: "press", aliases: ["click"], params: "PressActionParams (optional position)" },
|
|
2012
|
+
{ name: "longPress", params: "PressActionParams (optional position)" },
|
|
2013
|
+
{ name: "doubleTap", params: "none" },
|
|
2014
|
+
{
|
|
2015
|
+
name: "type",
|
|
2016
|
+
params: "TypeActionParams { text, delay?, clear? | clearFirst? } \u2014 `clear:true` replaces content atomically"
|
|
2017
|
+
},
|
|
2018
|
+
{ name: "clear", params: "none \u2014 empties the input" },
|
|
2019
|
+
{ name: "focus", params: "none" },
|
|
2020
|
+
{ name: "blur", params: "none" },
|
|
2021
|
+
{ name: "scroll", params: "ScrollActionParams { offset? {x,y}, to? }" },
|
|
2022
|
+
{ name: "swipe", params: "SwipeActionParams { direction, distance }" },
|
|
2023
|
+
{ name: "toggle", params: "none \u2014 flips boolean controls" }
|
|
2024
|
+
];
|
|
2025
|
+
function buildRoutesPayload() {
|
|
2026
|
+
const entries = [];
|
|
2027
|
+
for (const r of WS_ROUTES) {
|
|
2028
|
+
if (!r.httpMethods) continue;
|
|
2029
|
+
for (const m of r.httpMethods) {
|
|
2030
|
+
entries.push({ method: m, path: `/ui-bridge/${r.pattern}` });
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
entries.push({ method: "GET", path: "/ui-bridge/_help" });
|
|
2034
|
+
entries.push({ method: "GET", path: "/ui-bridge/_routes" });
|
|
2035
|
+
entries.sort((a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method));
|
|
2036
|
+
return { routes: entries, count: entries.length };
|
|
2037
|
+
}
|
|
2038
|
+
function buildHelpPayload() {
|
|
2039
|
+
return {
|
|
2040
|
+
version: 1,
|
|
2041
|
+
description: "UI Bridge Native HTTP surface. Prefix every path with /ui-bridge/.",
|
|
2042
|
+
routes: WS_ROUTES.map((r) => ({
|
|
2043
|
+
pattern: r.pattern,
|
|
2044
|
+
httpMethods: r.httpMethods ?? [],
|
|
2045
|
+
wsOnly: !r.httpMethods,
|
|
2046
|
+
handler: r.handler,
|
|
2047
|
+
description: HANDLER_DESCRIPTIONS[r.handler] ?? ""
|
|
2048
|
+
})),
|
|
2049
|
+
actions: ACTION_REFERENCE,
|
|
2050
|
+
tips: [
|
|
2051
|
+
"Start with `GET /ui-bridge/control/snapshot?visibleOnly=true` to see what the user actually sees.",
|
|
2052
|
+
"Prefer `control/component/:id/action/:actionId` over button presses \u2014 typed paramSchema, no button-id guessing.",
|
|
2053
|
+
"Use `pageNavigate` for tab switches instead of pressing tab buttons; gesture state often swallows clicks.",
|
|
2054
|
+
"The `type` action supports `clear:true` to replace existing text atomically in one call."
|
|
2055
|
+
]
|
|
2056
|
+
};
|
|
2057
|
+
}
|
|
1964
2058
|
var NativeUIBridgeServer = class {
|
|
1965
2059
|
constructor(registry, executor, config = {}) {
|
|
1966
2060
|
this.registry = registry;
|
|
@@ -1977,7 +2071,9 @@ var NativeUIBridgeServer = class {
|
|
|
1977
2071
|
cors: true,
|
|
1978
2072
|
...config
|
|
1979
2073
|
};
|
|
1980
|
-
this.handlers = createServerHandlers(registry, executor
|
|
2074
|
+
this.handlers = createServerHandlers(registry, executor, {
|
|
2075
|
+
appInfo: this.config.appInfo
|
|
2076
|
+
});
|
|
1981
2077
|
this.handlers.getMethods = async () => {
|
|
1982
2078
|
const methods = WS_ROUTES.map((r) => ({
|
|
1983
2079
|
method: r.pattern,
|
|
@@ -2781,6 +2877,20 @@ var NativeUIBridgeServer = class {
|
|
|
2781
2877
|
};
|
|
2782
2878
|
}
|
|
2783
2879
|
const stripped = path.slice(PREFIX.length);
|
|
2880
|
+
if (method === "GET" && stripped === "_help") {
|
|
2881
|
+
return {
|
|
2882
|
+
success: true,
|
|
2883
|
+
data: buildHelpPayload(),
|
|
2884
|
+
timestamp: Date.now()
|
|
2885
|
+
};
|
|
2886
|
+
}
|
|
2887
|
+
if (method === "GET" && stripped === "_routes") {
|
|
2888
|
+
return {
|
|
2889
|
+
success: true,
|
|
2890
|
+
data: buildRoutesPayload(),
|
|
2891
|
+
timestamp: Date.now()
|
|
2892
|
+
};
|
|
2893
|
+
}
|
|
2784
2894
|
let patternMatchedButWrongVerb = false;
|
|
2785
2895
|
for (const route of WS_ROUTES) {
|
|
2786
2896
|
const pathParams = parsePath(route.pattern, stripped);
|
|
@@ -3081,8 +3191,6 @@ var WebSocketEventBridge = class {
|
|
|
3081
3191
|
}, this.heartbeatIntervalMs);
|
|
3082
3192
|
}
|
|
3083
3193
|
};
|
|
3084
|
-
|
|
3085
|
-
// src/transport/DeviceAnnouncer.ts
|
|
3086
3194
|
var DEFAULT_PORT = 8087;
|
|
3087
3195
|
var RECONNECT_INITIAL_DELAY_MS = 2e3;
|
|
3088
3196
|
var RECONNECT_MAX_DELAY_MS = 6e4;
|
|
@@ -3103,15 +3211,27 @@ var DeviceAnnouncer = class {
|
|
|
3103
3211
|
}
|
|
3104
3212
|
// ── mDNS ──────────────────────────────────────────────────────────────────
|
|
3105
3213
|
/**
|
|
3106
|
-
* Start mDNS advertisement
|
|
3214
|
+
* Start mDNS advertisement.
|
|
3215
|
+
*
|
|
3216
|
+
* The consumer must pass the `Zeroconf` constructor (from `react-native-zeroconf`)
|
|
3217
|
+
* explicitly; otherwise this is a no-op.
|
|
3107
3218
|
*
|
|
3108
|
-
*
|
|
3219
|
+
* Rationale: Metro's `require()` throws an uncatchable module-load error if the
|
|
3220
|
+
* bundle doesn't include the named package. That error escapes async try/catch
|
|
3221
|
+
* boundaries and crashes the app. We avoid it by never calling `require()`
|
|
3222
|
+
* ourselves — the consumer imports the package when they know it's installed.
|
|
3223
|
+
*
|
|
3224
|
+
* @param ZeroconfCtor - constructor from `import Zeroconf from 'react-native-zeroconf'`
|
|
3109
3225
|
*/
|
|
3110
|
-
async startMdnsAdvertise() {
|
|
3226
|
+
async startMdnsAdvertise(ZeroconfCtor) {
|
|
3227
|
+
if (!ZeroconfCtor) {
|
|
3228
|
+
console.log(
|
|
3229
|
+
"[DeviceAnnouncer] mDNS advertisement skipped (no Zeroconf constructor provided). Pass one to enable mDNS."
|
|
3230
|
+
);
|
|
3231
|
+
return;
|
|
3232
|
+
}
|
|
3111
3233
|
try {
|
|
3112
|
-
|
|
3113
|
-
const Zeroconf = ZeroconfModule.default ?? ZeroconfModule;
|
|
3114
|
-
this.zeroconf = new Zeroconf();
|
|
3234
|
+
this.zeroconf = new ZeroconfCtor();
|
|
3115
3235
|
const port = this.config.port ?? DEFAULT_PORT;
|
|
3116
3236
|
const serviceName = `UIBridge-${this.config.deviceId.slice(0, 8)}`;
|
|
3117
3237
|
this.zeroconf.publishService("_uibridge", "_tcp.", "local.", serviceName, port, {
|
|
@@ -3122,10 +3242,8 @@ var DeviceAnnouncer = class {
|
|
|
3122
3242
|
});
|
|
3123
3243
|
this.state = { ...this.state, mdnsActive: true };
|
|
3124
3244
|
console.log(`[DeviceAnnouncer] mDNS: advertising "${serviceName}" on port ${port}`);
|
|
3125
|
-
} catch (
|
|
3126
|
-
console.warn(
|
|
3127
|
-
"[DeviceAnnouncer] react-native-zeroconf not available \u2014 mDNS advertisement skipped. Install it with: npx expo install react-native-zeroconf"
|
|
3128
|
-
);
|
|
3245
|
+
} catch (err) {
|
|
3246
|
+
console.warn("[DeviceAnnouncer] mDNS start failed:", err);
|
|
3129
3247
|
}
|
|
3130
3248
|
}
|
|
3131
3249
|
// ── Cloud relay ───────────────────────────────────────────────────────────
|
|
@@ -3230,12 +3348,7 @@ function generateHex(bytes) {
|
|
|
3230
3348
|
return Array.from(arr).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3231
3349
|
}
|
|
3232
3350
|
function getPlatform() {
|
|
3233
|
-
|
|
3234
|
-
const { Platform } = __require("react-native");
|
|
3235
|
-
return Platform.OS ?? "unknown";
|
|
3236
|
-
} catch {
|
|
3237
|
-
return "unknown";
|
|
3238
|
-
}
|
|
3351
|
+
return Platform?.OS ?? "unknown";
|
|
3239
3352
|
}
|
|
3240
3353
|
|
|
3241
3354
|
// src/transport/CloudRelayClient.ts
|
|
@@ -3442,7 +3555,8 @@ function UIBridgeNativeProvider({
|
|
|
3442
3555
|
}
|
|
3443
3556
|
const server = createNativeServer(registry, executor, {
|
|
3444
3557
|
serverPort: config.serverPort || 8087,
|
|
3445
|
-
cors: true
|
|
3558
|
+
cors: true,
|
|
3559
|
+
appInfo: config.appInfo
|
|
3446
3560
|
});
|
|
3447
3561
|
server.setAdapter(serverAdapter);
|
|
3448
3562
|
if (navigationProvider) {
|
|
@@ -3529,7 +3643,8 @@ function UIBridgeNativeProvider({
|
|
|
3529
3643
|
try {
|
|
3530
3644
|
const bareServer = createNativeServer(registry, executor, {
|
|
3531
3645
|
serverPort: config.serverPort || 8087,
|
|
3532
|
-
cors: true
|
|
3646
|
+
cors: true,
|
|
3647
|
+
appInfo: config.appInfo
|
|
3533
3648
|
});
|
|
3534
3649
|
if (navigationProvider) bareServer.setNavigationProvider(navigationProvider);
|
|
3535
3650
|
if (screenshotProvider) bareServer.setScreenshotProvider(screenshotProvider);
|