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 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>
@@ -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
+ }