objectiveai-viewer-sdk 2.0.5
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 +14 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# objectiveai-viewer-sdk
|
|
2
|
+
|
|
3
|
+
Plugin SDK for the [ObjectiveAI](https://objectiveai.dev) viewer. A thin TypeScript shim that lets plugin authors subscribe to events emitted by the host viewer from inside their iframe-mounted UI bundle, with the same `listen` surface as `@tauri-apps/api`.
|
|
4
|
+
|
|
5
|
+
Production context (loaded inside the host viewer): the plugin's `index.html` runs inside an `<iframe sandbox>` pointed at `plugin://localhost/<repo>/`. `window.parent` is the host viewer's React app. `listen()` registers a callback for incoming `{kind: 'plugin-event', type, value}` messages forwarded by the bridge.
|
|
6
|
+
|
|
7
|
+
Dev context (plugin author runs their own Tauri shell standalone): `window.parent === window` (no host). `listen()` falls through to `@tauri-apps/api`'s `listen`.
|
|
8
|
+
|
|
9
|
+
The plugin author writes the same code in both contexts.
|
|
10
|
+
|
|
11
|
+
## Links
|
|
12
|
+
|
|
13
|
+
- Homepage: <https://objectiveai.dev>
|
|
14
|
+
- Repository: <https://github.com/ObjectiveAI/objectiveai>
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* objectiveai-viewer-sdk
|
|
3
|
+
*
|
|
4
|
+
* Thin TypeScript shim that lets plugin authors subscribe to events
|
|
5
|
+
* emitted by the host viewer from inside their iframe-mounted UI
|
|
6
|
+
* bundle, with the same `listen` surface as `@tauri-apps/api`.
|
|
7
|
+
*
|
|
8
|
+
* Production context (loaded inside the host viewer):
|
|
9
|
+
* - The plugin's `index.html` runs inside an `<iframe sandbox>`
|
|
10
|
+
* pointed at `plugin://localhost/<repo>/`.
|
|
11
|
+
* - `window.parent` is the host viewer's React app.
|
|
12
|
+
* - `listen()` registers a callback for incoming
|
|
13
|
+
* `{kind: 'plugin-event', type, value}` messages forwarded by the
|
|
14
|
+
* bridge from the Rust-side `Event::Plugin` emissions.
|
|
15
|
+
*
|
|
16
|
+
* Dev context (plugin author runs their own Tauri shell standalone):
|
|
17
|
+
* - `window.parent === window` (no host).
|
|
18
|
+
* - `listen()` falls through to `@tauri-apps/api`'s `listen`.
|
|
19
|
+
*
|
|
20
|
+
* The plugin author writes the same code in both contexts.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Register a handler for incoming plugin events. Returns an
|
|
24
|
+
* unsubscribe function. In iframe context the events come from the
|
|
25
|
+
* host's bridge; in standalone-dev context they come from
|
|
26
|
+
* `@tauri-apps/api`'s `listen`.
|
|
27
|
+
*
|
|
28
|
+
* `type` matches the `type` field of the `Event` emitted by the
|
|
29
|
+
* Rust backend — the string the plugin author registered in their
|
|
30
|
+
* manifest's `viewer_routes` entry.
|
|
31
|
+
*/
|
|
32
|
+
export declare function listen<T = unknown>(type: string, handler: (value: T) => void): () => void;
|
|
33
|
+
/** Internal-use: clear in-flight state. Exposed for tests only.
|
|
34
|
+
* Note: the module-level `message` event listener stays attached —
|
|
35
|
+
* removing/re-attaching it would just register a duplicate. The
|
|
36
|
+
* listeners map is what carries per-test state. */
|
|
37
|
+
export declare function __resetForTests(): void;
|
|
38
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAsCH;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CAAC,CAAC,GAAG,OAAO,EAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAC1B,MAAM,IAAI,CAyCZ;AAED;;;mDAGmD;AACnD,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* objectiveai-viewer-sdk
|
|
3
|
+
*
|
|
4
|
+
* Thin TypeScript shim that lets plugin authors subscribe to events
|
|
5
|
+
* emitted by the host viewer from inside their iframe-mounted UI
|
|
6
|
+
* bundle, with the same `listen` surface as `@tauri-apps/api`.
|
|
7
|
+
*
|
|
8
|
+
* Production context (loaded inside the host viewer):
|
|
9
|
+
* - The plugin's `index.html` runs inside an `<iframe sandbox>`
|
|
10
|
+
* pointed at `plugin://localhost/<repo>/`.
|
|
11
|
+
* - `window.parent` is the host viewer's React app.
|
|
12
|
+
* - `listen()` registers a callback for incoming
|
|
13
|
+
* `{kind: 'plugin-event', type, value}` messages forwarded by the
|
|
14
|
+
* bridge from the Rust-side `Event::Plugin` emissions.
|
|
15
|
+
*
|
|
16
|
+
* Dev context (plugin author runs their own Tauri shell standalone):
|
|
17
|
+
* - `window.parent === window` (no host).
|
|
18
|
+
* - `listen()` falls through to `@tauri-apps/api`'s `listen`.
|
|
19
|
+
*
|
|
20
|
+
* The plugin author writes the same code in both contexts.
|
|
21
|
+
*/
|
|
22
|
+
/** True when running inside an iframe in the host viewer. */
|
|
23
|
+
function isInIframe() {
|
|
24
|
+
return typeof window !== "undefined" && window.parent !== window;
|
|
25
|
+
}
|
|
26
|
+
const listeners = new Map();
|
|
27
|
+
let messageHandlerAttached = false;
|
|
28
|
+
function attachMessageHandler() {
|
|
29
|
+
if (messageHandlerAttached)
|
|
30
|
+
return;
|
|
31
|
+
if (typeof window === "undefined")
|
|
32
|
+
return;
|
|
33
|
+
window.addEventListener("message", (event) => {
|
|
34
|
+
const msg = event.data;
|
|
35
|
+
if (!msg || typeof msg !== "object")
|
|
36
|
+
return;
|
|
37
|
+
if (msg.kind !== "plugin-event")
|
|
38
|
+
return;
|
|
39
|
+
const set = listeners.get(msg.type);
|
|
40
|
+
if (!set)
|
|
41
|
+
return;
|
|
42
|
+
for (const fn of set) {
|
|
43
|
+
try {
|
|
44
|
+
fn(msg.value);
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
// Don't let one handler take down the others.
|
|
48
|
+
// eslint-disable-next-line no-console
|
|
49
|
+
console.error("objectiveai-viewer-sdk listener threw:", e);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
messageHandlerAttached = true;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Register a handler for incoming plugin events. Returns an
|
|
57
|
+
* unsubscribe function. In iframe context the events come from the
|
|
58
|
+
* host's bridge; in standalone-dev context they come from
|
|
59
|
+
* `@tauri-apps/api`'s `listen`.
|
|
60
|
+
*
|
|
61
|
+
* `type` matches the `type` field of the `Event` emitted by the
|
|
62
|
+
* Rust backend — the string the plugin author registered in their
|
|
63
|
+
* manifest's `viewer_routes` entry.
|
|
64
|
+
*/
|
|
65
|
+
export function listen(type, handler) {
|
|
66
|
+
if (!isInIframe()) {
|
|
67
|
+
// Standalone dev mode: register via @tauri-apps/api.
|
|
68
|
+
let unlisten = null;
|
|
69
|
+
let cancelled = false;
|
|
70
|
+
void (async () => {
|
|
71
|
+
try {
|
|
72
|
+
const mod = await import("@tauri-apps/api/event");
|
|
73
|
+
if (cancelled)
|
|
74
|
+
return;
|
|
75
|
+
const u = await mod.listen(`plugin-${type}`, (e) => handler(e.payload?.value));
|
|
76
|
+
if (cancelled) {
|
|
77
|
+
u();
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
unlisten = u;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// eslint-disable-next-line no-console
|
|
85
|
+
console.warn(`objectiveai-viewer-sdk: listen('${type}') called outside an iframe and ` +
|
|
86
|
+
`@tauri-apps/api is unavailable; events will not fire.`);
|
|
87
|
+
}
|
|
88
|
+
})();
|
|
89
|
+
return () => {
|
|
90
|
+
cancelled = true;
|
|
91
|
+
if (unlisten)
|
|
92
|
+
unlisten();
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
attachMessageHandler();
|
|
96
|
+
const set = listeners.get(type) ?? new Set();
|
|
97
|
+
const fn = (value) => handler(value);
|
|
98
|
+
set.add(fn);
|
|
99
|
+
listeners.set(type, set);
|
|
100
|
+
return () => {
|
|
101
|
+
const s = listeners.get(type);
|
|
102
|
+
if (!s)
|
|
103
|
+
return;
|
|
104
|
+
s.delete(fn);
|
|
105
|
+
if (s.size === 0)
|
|
106
|
+
listeners.delete(type);
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/** Internal-use: clear in-flight state. Exposed for tests only.
|
|
110
|
+
* Note: the module-level `message` event listener stays attached —
|
|
111
|
+
* removing/re-attaching it would just register a duplicate. The
|
|
112
|
+
* listeners map is what carries per-test state. */
|
|
113
|
+
export function __resetForTests() {
|
|
114
|
+
listeners.clear();
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "objectiveai-viewer-sdk",
|
|
3
|
+
"version": "2.0.5",
|
|
4
|
+
"description": "Plugin SDK for the ObjectiveAI viewer: typed iframe-bridge for receiving host events.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "shx rm -rf dist && tsc -p tsconfig.build.json",
|
|
19
|
+
"test": "vitest run",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"prepublishOnly": "pnpm run build"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/ObjectiveAI/objectiveai.git"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://objectiveai.dev",
|
|
28
|
+
"author": {
|
|
29
|
+
"name": "ObjectiveAI",
|
|
30
|
+
"email": "admin@objectiveai.dev",
|
|
31
|
+
"url": "https://objectiveai.dev"
|
|
32
|
+
},
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"objectiveai",
|
|
39
|
+
"viewer",
|
|
40
|
+
"plugin",
|
|
41
|
+
"sdk"
|
|
42
|
+
],
|
|
43
|
+
"sideEffects": false,
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"jsdom": "^29.1.1",
|
|
46
|
+
"shx": "^0.4.0",
|
|
47
|
+
"typescript": "^5.9.3",
|
|
48
|
+
"vitest": "^2.1.5"
|
|
49
|
+
}
|
|
50
|
+
}
|