@aiworkbench/vibe-bridge 0.0.2 → 0.0.3

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.
Files changed (36) hide show
  1. package/dist/adapters/api.d.ts +6 -0
  2. package/dist/adapters/api.d.ts.map +1 -0
  3. package/dist/adapters/auth.d.ts +12 -0
  4. package/dist/adapters/auth.d.ts.map +1 -0
  5. package/dist/adapters/events.d.ts +3 -0
  6. package/dist/adapters/events.d.ts.map +1 -0
  7. package/dist/adapters/navigation.d.ts +6 -0
  8. package/dist/adapters/navigation.d.ts.map +1 -0
  9. package/dist/adapters/storage.d.ts +3 -0
  10. package/dist/adapters/storage.d.ts.map +1 -0
  11. package/dist/adapters/theme.d.ts +3 -0
  12. package/dist/adapters/theme.d.ts.map +1 -0
  13. package/dist/adapters/toast.d.ts +11 -0
  14. package/dist/adapters/toast.d.ts.map +1 -0
  15. package/dist/components/VibeErrorBoundary.d.ts +17 -0
  16. package/dist/components/VibeErrorBoundary.d.ts.map +1 -0
  17. package/dist/components/VibeHost.d.ts +3 -0
  18. package/dist/components/VibeHost.d.ts.map +1 -0
  19. package/dist/core/event-bus.d.ts +10 -0
  20. package/dist/core/event-bus.d.ts.map +1 -0
  21. package/dist/core/loader.d.ts +3 -0
  22. package/dist/core/loader.d.ts.map +1 -0
  23. package/dist/core/permissions.d.ts +3 -0
  24. package/dist/core/permissions.d.ts.map +1 -0
  25. package/dist/core/types.d.ts +40 -0
  26. package/dist/core/types.d.ts.map +1 -0
  27. package/dist/hooks/useVibeBridge.d.ts +9 -0
  28. package/dist/hooks/useVibeBridge.d.ts.map +1 -0
  29. package/dist/hooks/useVibeEvents.d.ts +2 -0
  30. package/dist/hooks/useVibeEvents.d.ts.map +1 -0
  31. package/dist/hooks/useVibeLoader.d.ts +3 -0
  32. package/dist/hooks/useVibeLoader.d.ts.map +1 -0
  33. package/dist/index.d.ts +20 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +450 -0
  36. package/package.json +4 -3
@@ -0,0 +1,6 @@
1
+ import type { ApiBridge } from "@aiworkbench/vibe-types";
2
+ export interface ApiAdapterDeps {
3
+ getToken: () => Promise<string>;
4
+ }
5
+ export declare function createApiAdapter(deps: ApiAdapterDeps): ApiBridge;
6
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/adapters/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CACjC;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,CAiBhE"}
@@ -0,0 +1,12 @@
1
+ import type { AuthBridge } from "@aiworkbench/vibe-types";
2
+ export interface AuthAdapterDeps {
3
+ session: {
4
+ user?: {
5
+ name?: string | null;
6
+ email?: string | null;
7
+ } | null;
8
+ idToken?: string;
9
+ } | null;
10
+ }
11
+ export declare function createAuthAdapter(deps: AuthAdapterDeps): AuthBridge;
12
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/adapters/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,yBAAyB,CAAC;AAEtE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE;QACP,IAAI,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,GAAG,IAAI,CAAC;QAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,IAAI,CAAC;CACV;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,UAAU,CAkBnE"}
@@ -0,0 +1,3 @@
1
+ import type { EventsBridge } from "@aiworkbench/vibe-types";
2
+ export declare function createEventsAdapter(appId: string): EventsBridge;
3
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/adapters/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,yBAAyB,CAAC;AAG1E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAY/D"}
@@ -0,0 +1,6 @@
1
+ import type { NavigationBridge } from "@aiworkbench/vibe-types";
2
+ export interface NavigationAdapterDeps {
3
+ push: (path: string) => void;
4
+ }
5
+ export declare function createNavigationAdapter(deps: NavigationAdapterDeps): NavigationBridge;
6
+ //# sourceMappingURL=navigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/adapters/navigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,qBAAqB,GAC1B,gBAAgB,CAYlB"}
@@ -0,0 +1,3 @@
1
+ import type { StorageBridge } from "@aiworkbench/vibe-types";
2
+ export declare function createStorageAdapter(appId: string): StorageBridge;
3
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/adapters/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAwBjE"}
@@ -0,0 +1,3 @@
1
+ import type { ThemeBridge } from "@aiworkbench/vibe-types";
2
+ export declare function createThemeAdapter(): ThemeBridge;
3
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/adapters/theme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,wBAAgB,kBAAkB,IAAI,WAAW,CAqBhD"}
@@ -0,0 +1,11 @@
1
+ import type { ToastBridge } from "@aiworkbench/vibe-types";
2
+ export interface ToastAdapterDeps {
3
+ toast: {
4
+ (message: string): void;
5
+ success: (message: string) => void;
6
+ error: (message: string) => void;
7
+ info: (message: string) => void;
8
+ };
9
+ }
10
+ export declare function createToastAdapter(deps: ToastAdapterDeps): ToastBridge;
11
+ //# sourceMappingURL=toast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../../src/adapters/toast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE;QACL,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;QACnC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;QACjC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KACjC,CAAC;CACH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,CAsBtE"}
@@ -0,0 +1,17 @@
1
+ import { Component, type ReactNode, type ErrorInfo } from "react";
2
+ interface VibeErrorBoundaryProps {
3
+ fallback: (error: Error) => ReactNode;
4
+ onError?: (error: Error) => void;
5
+ children: ReactNode;
6
+ }
7
+ interface VibeErrorBoundaryState {
8
+ error: Error | null;
9
+ }
10
+ export declare class VibeErrorBoundary extends Component<VibeErrorBoundaryProps, VibeErrorBoundaryState> {
11
+ constructor(props: VibeErrorBoundaryProps);
12
+ static getDerivedStateFromError(error: Error): VibeErrorBoundaryState;
13
+ componentDidCatch(error: Error, _info: ErrorInfo): void;
14
+ render(): ReactNode;
15
+ }
16
+ export {};
17
+ //# sourceMappingURL=VibeErrorBoundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VibeErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/components/VibeErrorBoundary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElE,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC;IACtC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,UAAU,sBAAsB;IAC9B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,qBAAa,iBAAkB,SAAQ,SAAS,CAC9C,sBAAsB,EACtB,sBAAsB,CACvB;gBACa,KAAK,EAAE,sBAAsB;IAKzC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,sBAAsB;IAIrE,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI;IAIvD,MAAM,IAAI,SAAS;CAMpB"}
@@ -0,0 +1,3 @@
1
+ import type { VibeHostProps } from "../core/types";
2
+ export declare function VibeHost(props: VibeHostProps): import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=VibeHost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VibeHost.d.ts","sourceRoot":"","sources":["../../src/components/VibeHost.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAiFnD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,2CAiB5C"}
@@ -0,0 +1,10 @@
1
+ export interface VibeEventDetail {
2
+ payload: Record<string, unknown>;
3
+ sourceAppId: string;
4
+ }
5
+ export declare function getEventBus(): EventTarget;
6
+ export declare function prefixedEventName(event: string): string;
7
+ export declare function emitEvent(event: string, payload: Record<string, unknown>, sourceAppId: string): void;
8
+ export declare function onEvent(event: string, handler: (detail: VibeEventDetail) => void): () => void;
9
+ export declare function onceEvent(event: string, handler: (detail: VibeEventDetail) => void): () => void;
10
+ //# sourceMappingURL=event-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/core/event-bus.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;CACrB;AAID,wBAAgB,WAAW,IAAI,WAAW,CAKzC;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,WAAW,EAAE,MAAM,GAClB,IAAI,CAMN;AAED,wBAAgB,OAAO,CACrB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,GACzC,MAAM,IAAI,CAQZ;AAED,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,GACzC,MAAM,IAAI,CAQZ"}
@@ -0,0 +1,3 @@
1
+ export declare function loadScript(src: string): Promise<void>;
2
+ export declare function waitForElement(tagName: string): Promise<void>;
3
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/core/loader.ts"],"names":[],"mappings":"AAmBA,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BrD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7D"}
@@ -0,0 +1,3 @@
1
+ import type { Bridge, BridgeCapability } from "@aiworkbench/vibe-types";
2
+ export declare function filterByPermissions(bridge: Bridge, permissions: BridgeCapability[]): Bridge;
3
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/core/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAgBxE,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,gBAAgB,EAAE,GAC9B,MAAM,CAqBR"}
@@ -0,0 +1,40 @@
1
+ import type { Bridge, VibeManifest, AuthBridge, ApiBridge, NavigationBridge, ThemeBridge, ToastBridge, StorageBridge, EventsBridge } from "@aiworkbench/vibe-types";
2
+ import type { ReactNode, CSSProperties } from "react";
3
+ export interface VibeHostProps {
4
+ /** The mini-app manifest describing its id, permissions, etc. */
5
+ manifest: VibeManifest;
6
+ /** URL to the built JS bundle for the mini-app. */
7
+ src: string;
8
+ /** Shown while the script loads and custom element registers. */
9
+ fallback?: ReactNode;
10
+ /** Shown when the script fails to load or the element fails to mount. */
11
+ errorFallback?: (error: Error) => ReactNode;
12
+ /** Optional overrides per capability adapter. */
13
+ adapters?: Partial<AdapterOverrides>;
14
+ /** Fires when the custom element is mounted and bridge is injected. */
15
+ onReady?: () => void;
16
+ /** Fires on load or mount failure. */
17
+ onError?: (error: Error) => void;
18
+ className?: string;
19
+ style?: CSSProperties;
20
+ }
21
+ export interface AdapterOverrides {
22
+ auth: AuthBridge;
23
+ api: ApiBridge;
24
+ navigation: NavigationBridge;
25
+ theme: ThemeBridge;
26
+ toast: ToastBridge;
27
+ storage: StorageBridge;
28
+ events: EventsBridge;
29
+ }
30
+ export type LoaderStatus = "loading" | "ready" | "error";
31
+ export interface UseVibeLoaderResult {
32
+ status: LoaderStatus;
33
+ error: Error | null;
34
+ }
35
+ export interface UseVibeBridgeOptions {
36
+ appId: string;
37
+ permissions: Bridge extends infer B ? (keyof B)[] : never;
38
+ overrides?: Partial<AdapterOverrides>;
39
+ }
40
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EACZ,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,aAAa,EACb,YAAY,EACb,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,QAAQ,EAAE,YAAY,CAAC;IACvB,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,iEAAiE;IACjE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,yEAAyE;IACzE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC;IAC5C,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACrC,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,sCAAsC;IACtC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,EAAE,SAAS,CAAC;IACf,UAAU,EAAE,gBAAgB,CAAC;IAC7B,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,SAAS,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC;IAC1D,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACvC"}
@@ -0,0 +1,9 @@
1
+ import type { Bridge, BridgeCapability } from "@aiworkbench/vibe-types";
2
+ import type { AdapterOverrides } from "../core/types";
3
+ export interface UseVibeBridgeOptions {
4
+ appId: string;
5
+ permissions: BridgeCapability[];
6
+ overrides?: Partial<AdapterOverrides>;
7
+ }
8
+ export declare function useVibeBridge(options: UseVibeBridgeOptions): Bridge;
9
+ //# sourceMappingURL=useVibeBridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVibeBridge.d.ts","sourceRoot":"","sources":["../../src/hooks/useVibeBridge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAYxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACvC;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CA2BnE"}
@@ -0,0 +1,2 @@
1
+ export declare function useVibeEvents(event: string, handler: (payload: Record<string, unknown>, sourceAppId: string) => void): void;
2
+ //# sourceMappingURL=useVibeEvents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVibeEvents.d.ts","sourceRoot":"","sources":["../../src/hooks/useVibeEvents.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,GACvE,IAAI,CAMN"}
@@ -0,0 +1,3 @@
1
+ import type { UseVibeLoaderResult } from "../core/types";
2
+ export declare function useVibeLoader(src: string, tagName: string): UseVibeLoaderResult;
3
+ //# sourceMappingURL=useVibeLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVibeLoader.d.ts","sourceRoot":"","sources":["../../src/hooks/useVibeLoader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEvE,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,GACd,mBAAmB,CAkCrB"}
@@ -0,0 +1,20 @@
1
+ export { VibeHost } from "./components/VibeHost";
2
+ export { VibeErrorBoundary } from "./components/VibeErrorBoundary";
3
+ export { useVibeBridge } from "./hooks/useVibeBridge";
4
+ export { useVibeLoader } from "./hooks/useVibeLoader";
5
+ export { useVibeEvents } from "./hooks/useVibeEvents";
6
+ export { createAuthAdapter } from "./adapters/auth";
7
+ export { createApiAdapter } from "./adapters/api";
8
+ export { createNavigationAdapter } from "./adapters/navigation";
9
+ export { createThemeAdapter } from "./adapters/theme";
10
+ export { createToastAdapter } from "./adapters/toast";
11
+ export { createStorageAdapter } from "./adapters/storage";
12
+ export { createEventsAdapter } from "./adapters/events";
13
+ export { filterByPermissions } from "./core/permissions";
14
+ export { getEventBus, emitEvent } from "./core/event-bus";
15
+ export type { VibeHostProps, AdapterOverrides, LoaderStatus, UseVibeLoaderResult, } from "./core/types";
16
+ export type { AuthAdapterDeps } from "./adapters/auth";
17
+ export type { ApiAdapterDeps } from "./adapters/api";
18
+ export type { NavigationAdapterDeps } from "./adapters/navigation";
19
+ export type { ToastAdapterDeps } from "./adapters/toast";
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGnE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG1D,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,450 @@
1
+ // src/components/VibeHost.tsx
2
+ import { useRef, useEffect as useEffect2, useCallback } from "react";
3
+
4
+ // src/hooks/useVibeLoader.ts
5
+ import { useState, useEffect } from "react";
6
+
7
+ // src/core/loader.ts
8
+ var loadedScripts = new Set;
9
+ var ALLOWED_PROTOCOLS = new Set(["https:", "http:"]);
10
+ function validateScriptSrc(src) {
11
+ let url;
12
+ try {
13
+ url = new URL(src, window.location.href);
14
+ } catch {
15
+ return `Invalid vibe app script URL: ${src}`;
16
+ }
17
+ if (!ALLOWED_PROTOCOLS.has(url.protocol)) {
18
+ return `Refused to load vibe app script with disallowed protocol "${url.protocol}": ${src}`;
19
+ }
20
+ return null;
21
+ }
22
+ function loadScript(src) {
23
+ const validationError = validateScriptSrc(src);
24
+ if (validationError) {
25
+ return Promise.reject(new Error(validationError));
26
+ }
27
+ if (loadedScripts.has(src)) {
28
+ return Promise.resolve();
29
+ }
30
+ return new Promise((resolve, reject) => {
31
+ const existing = document.querySelector(`script[src="${CSS.escape(src)}"]`);
32
+ if (existing) {
33
+ loadedScripts.add(src);
34
+ resolve();
35
+ return;
36
+ }
37
+ const script = document.createElement("script");
38
+ script.type = "module";
39
+ script.src = src;
40
+ script.onload = () => {
41
+ loadedScripts.add(src);
42
+ resolve();
43
+ };
44
+ script.onerror = () => {
45
+ reject(new Error(`Failed to load vibe app script: ${src}`));
46
+ };
47
+ document.head.appendChild(script);
48
+ });
49
+ }
50
+ function waitForElement(tagName) {
51
+ if (customElements.get(tagName)) {
52
+ return Promise.resolve();
53
+ }
54
+ return customElements.whenDefined(tagName).then(() => {
55
+ return;
56
+ });
57
+ }
58
+
59
+ // src/hooks/useVibeLoader.ts
60
+ function useVibeLoader(src, tagName) {
61
+ const [status, setStatus] = useState("loading");
62
+ const [error, setError] = useState(null);
63
+ useEffect(() => {
64
+ let cancelled = false;
65
+ setStatus("loading");
66
+ setError(null);
67
+ loadScript(src).then(() => waitForElement(tagName)).then(() => {
68
+ if (!cancelled) {
69
+ setStatus("ready");
70
+ }
71
+ }).catch((err) => {
72
+ if (!cancelled) {
73
+ const e = err instanceof Error ? err : new Error(`Failed to load vibe app: ${tagName}`);
74
+ setError(e);
75
+ setStatus("error");
76
+ }
77
+ });
78
+ return () => {
79
+ cancelled = true;
80
+ };
81
+ }, [src, tagName]);
82
+ return { status, error };
83
+ }
84
+
85
+ // src/hooks/useVibeBridge.ts
86
+ import { useMemo } from "react";
87
+ import { useSession } from "next-auth/react";
88
+ import { useRouter } from "next/navigation";
89
+ import { toast } from "sonner";
90
+
91
+ // src/adapters/auth.ts
92
+ function createAuthAdapter(deps) {
93
+ return {
94
+ getUser() {
95
+ const user = deps.session?.user;
96
+ return {
97
+ id: user?.email ?? "unknown",
98
+ name: user?.name ?? "Unknown User",
99
+ email: user?.email ?? undefined
100
+ };
101
+ },
102
+ async getToken() {
103
+ const token = deps.session?.idToken;
104
+ if (!token) {
105
+ throw new Error("No authentication token available.");
106
+ }
107
+ return token;
108
+ }
109
+ };
110
+ }
111
+
112
+ // src/adapters/api.ts
113
+ function createApiAdapter(deps) {
114
+ return {
115
+ async fetch(endpoint, options) {
116
+ const url = endpoint.startsWith("/api/") ? endpoint : `/api/${endpoint.replace(/^\//, "")}`;
117
+ const token = await deps.getToken();
118
+ const headers = new Headers(options?.headers);
119
+ headers.set("Authorization", `Bearer ${token}`);
120
+ return globalThis.fetch(url, {
121
+ ...options,
122
+ headers
123
+ });
124
+ }
125
+ };
126
+ }
127
+
128
+ // src/adapters/navigation.ts
129
+ function createNavigationAdapter(deps) {
130
+ return {
131
+ navigate(path) {
132
+ if (/^https?:\/\//i.test(path) || /^javascript:/i.test(path)) {
133
+ throw new Error(`Navigation to external URLs is not allowed: ${path}`);
134
+ }
135
+ deps.push(path);
136
+ }
137
+ };
138
+ }
139
+
140
+ // src/adapters/theme.ts
141
+ function createThemeAdapter() {
142
+ return {
143
+ current() {
144
+ const html = document.documentElement;
145
+ if (html.classList.contains("dark"))
146
+ return "dark";
147
+ if (html.classList.contains("light"))
148
+ return "light";
149
+ const dataTheme = html.getAttribute("data-theme");
150
+ if (dataTheme === "dark")
151
+ return "dark";
152
+ if (dataTheme === "light")
153
+ return "light";
154
+ if (globalThis.matchMedia?.("(prefers-color-scheme: dark)").matches) {
155
+ return "dark";
156
+ }
157
+ return "light";
158
+ }
159
+ };
160
+ }
161
+
162
+ // src/adapters/toast.ts
163
+ function createToastAdapter(deps) {
164
+ return {
165
+ show(message, options) {
166
+ const type = options?.type ?? "info";
167
+ switch (type) {
168
+ case "success":
169
+ deps.toast.success(message);
170
+ break;
171
+ case "error":
172
+ deps.toast.error(message);
173
+ break;
174
+ case "info":
175
+ deps.toast.info(message);
176
+ break;
177
+ default:
178
+ deps.toast(message);
179
+ }
180
+ }
181
+ };
182
+ }
183
+
184
+ // src/adapters/storage.ts
185
+ function createStorageAdapter(appId) {
186
+ const prefix = `vibe:${appId}:`;
187
+ return {
188
+ async get(key) {
189
+ return localStorage.getItem(`${prefix}${key}`);
190
+ },
191
+ async set(key, value) {
192
+ localStorage.setItem(`${prefix}${key}`, value);
193
+ },
194
+ async remove(key) {
195
+ localStorage.removeItem(`${prefix}${key}`);
196
+ },
197
+ async keys() {
198
+ const result = [];
199
+ for (let i = 0;i < localStorage.length; i++) {
200
+ const k = localStorage.key(i);
201
+ if (k?.startsWith(prefix)) {
202
+ result.push(k.slice(prefix.length));
203
+ }
204
+ }
205
+ return result;
206
+ }
207
+ };
208
+ }
209
+
210
+ // src/core/event-bus.ts
211
+ var VIBE_EVENT_PREFIX = "vibe:";
212
+ var sharedBus = null;
213
+ function getEventBus() {
214
+ if (!sharedBus) {
215
+ sharedBus = new EventTarget;
216
+ }
217
+ return sharedBus;
218
+ }
219
+ function prefixedEventName(event) {
220
+ if (event.startsWith(VIBE_EVENT_PREFIX)) {
221
+ return event;
222
+ }
223
+ return `${VIBE_EVENT_PREFIX}${event}`;
224
+ }
225
+ function emitEvent(event, payload, sourceAppId) {
226
+ const bus = getEventBus();
227
+ const detail = { payload, sourceAppId };
228
+ bus.dispatchEvent(new CustomEvent(prefixedEventName(event), { detail }));
229
+ }
230
+ function onEvent(event, handler) {
231
+ const bus = getEventBus();
232
+ const prefixed = prefixedEventName(event);
233
+ const listener = (e) => {
234
+ handler(e.detail);
235
+ };
236
+ bus.addEventListener(prefixed, listener);
237
+ return () => bus.removeEventListener(prefixed, listener);
238
+ }
239
+ function onceEvent(event, handler) {
240
+ const bus = getEventBus();
241
+ const prefixed = prefixedEventName(event);
242
+ const listener = (e) => {
243
+ handler(e.detail);
244
+ };
245
+ bus.addEventListener(prefixed, listener, { once: true });
246
+ return () => bus.removeEventListener(prefixed, listener);
247
+ }
248
+
249
+ // src/adapters/events.ts
250
+ function createEventsAdapter(appId) {
251
+ return {
252
+ emit(event, payload) {
253
+ emitEvent(event, payload ?? {}, appId);
254
+ },
255
+ on(event, handler) {
256
+ return onEvent(event, (detail) => handler(detail.payload));
257
+ },
258
+ once(event, handler) {
259
+ return onceEvent(event, (detail) => handler(detail.payload));
260
+ }
261
+ };
262
+ }
263
+
264
+ // src/core/permissions.ts
265
+ function createDeniedProxy(capability) {
266
+ return new Proxy({}, {
267
+ get(_target, prop) {
268
+ if (typeof prop === "symbol")
269
+ return;
270
+ throw new Error(`Access denied: ${capability}.${prop} is not permitted. Add '${capability}' to your manifest.json permissions.`);
271
+ }
272
+ });
273
+ }
274
+ function filterByPermissions(bridge, permissions) {
275
+ const allCapabilities = [
276
+ "auth",
277
+ "api",
278
+ "navigation",
279
+ "theme",
280
+ "toast",
281
+ "storage",
282
+ "events"
283
+ ];
284
+ const filtered = {};
285
+ for (const cap of allCapabilities) {
286
+ if (permissions.includes(cap)) {
287
+ filtered[cap] = bridge[cap];
288
+ } else {
289
+ filtered[cap] = createDeniedProxy(cap);
290
+ }
291
+ }
292
+ return filtered;
293
+ }
294
+
295
+ // src/hooks/useVibeBridge.ts
296
+ function useVibeBridge(options) {
297
+ const { appId, permissions, overrides } = options;
298
+ const { data: session } = useSession();
299
+ const router = useRouter();
300
+ return useMemo(() => {
301
+ const authAdapter = overrides?.auth ?? createAuthAdapter({ session: session ?? null });
302
+ const fullBridge = {
303
+ auth: authAdapter,
304
+ api: overrides?.api ?? createApiAdapter({ getToken: () => authAdapter.getToken() }),
305
+ navigation: overrides?.navigation ?? createNavigationAdapter({ push: (path) => router.push(path) }),
306
+ theme: overrides?.theme ?? createThemeAdapter(),
307
+ toast: overrides?.toast ?? createToastAdapter({ toast }),
308
+ storage: overrides?.storage ?? createStorageAdapter(appId),
309
+ events: overrides?.events ?? createEventsAdapter(appId)
310
+ };
311
+ return filterByPermissions(fullBridge, permissions);
312
+ }, [session, router, appId, permissions, overrides]);
313
+ }
314
+
315
+ // src/components/VibeErrorBoundary.tsx
316
+ import { Component } from "react";
317
+
318
+ class VibeErrorBoundary extends Component {
319
+ constructor(props) {
320
+ super(props);
321
+ this.state = { error: null };
322
+ }
323
+ static getDerivedStateFromError(error) {
324
+ return { error };
325
+ }
326
+ componentDidCatch(error, _info) {
327
+ this.props.onError?.(error);
328
+ }
329
+ render() {
330
+ if (this.state.error) {
331
+ return this.props.fallback(this.state.error);
332
+ }
333
+ return this.props.children;
334
+ }
335
+ }
336
+
337
+ // src/components/VibeHost.tsx
338
+ import { jsxDEV, Fragment } from "react/jsx-dev-runtime";
339
+ function VibeHostInner({
340
+ manifest,
341
+ src,
342
+ fallback,
343
+ errorFallback,
344
+ adapters,
345
+ onReady,
346
+ onError,
347
+ className,
348
+ style
349
+ }) {
350
+ const containerRef = useRef(null);
351
+ const elementRef = useRef(null);
352
+ const readyFiredRef = useRef(false);
353
+ const { status, error: loadError } = useVibeLoader(src, manifest.id);
354
+ const bridge = useVibeBridge({
355
+ appId: manifest.id,
356
+ permissions: manifest.permissions,
357
+ overrides: adapters
358
+ });
359
+ useEffect2(() => {
360
+ if (loadError) {
361
+ onError?.(loadError);
362
+ }
363
+ }, [loadError, onError]);
364
+ useEffect2(() => {
365
+ const container = containerRef.current;
366
+ if (status !== "ready" || !container)
367
+ return;
368
+ const el = document.createElement(manifest.id);
369
+ el.bridge = bridge;
370
+ container.appendChild(el);
371
+ elementRef.current = el;
372
+ if (!readyFiredRef.current) {
373
+ readyFiredRef.current = true;
374
+ onReady?.();
375
+ }
376
+ return () => {
377
+ if (container.contains(el)) {
378
+ container.removeChild(el);
379
+ }
380
+ elementRef.current = null;
381
+ };
382
+ }, [status, manifest.id]);
383
+ useEffect2(() => {
384
+ if (elementRef.current) {
385
+ elementRef.current.bridge = bridge;
386
+ }
387
+ }, [bridge]);
388
+ if (status === "error" && loadError) {
389
+ if (errorFallback) {
390
+ return /* @__PURE__ */ jsxDEV(Fragment, {
391
+ children: errorFallback(loadError)
392
+ }, undefined, false, undefined, this);
393
+ }
394
+ return null;
395
+ }
396
+ if (status === "loading") {
397
+ return /* @__PURE__ */ jsxDEV(Fragment, {
398
+ children: fallback ?? null
399
+ }, undefined, false, undefined, this);
400
+ }
401
+ return /* @__PURE__ */ jsxDEV("div", {
402
+ ref: containerRef,
403
+ className,
404
+ style
405
+ }, undefined, false, undefined, this);
406
+ }
407
+ function VibeHost(props) {
408
+ const defaultErrorFallback = useCallback((error) => {
409
+ props.onError?.(error);
410
+ if (props.errorFallback) {
411
+ return /* @__PURE__ */ jsxDEV(Fragment, {
412
+ children: props.errorFallback(error)
413
+ }, undefined, false, undefined, this);
414
+ }
415
+ return null;
416
+ }, [props.onError, props.errorFallback]);
417
+ return /* @__PURE__ */ jsxDEV(VibeErrorBoundary, {
418
+ fallback: defaultErrorFallback,
419
+ onError: props.onError,
420
+ children: /* @__PURE__ */ jsxDEV(VibeHostInner, {
421
+ ...props
422
+ }, undefined, false, undefined, this)
423
+ }, undefined, false, undefined, this);
424
+ }
425
+ // src/hooks/useVibeEvents.ts
426
+ import { useEffect as useEffect3 } from "react";
427
+ function useVibeEvents(event, handler) {
428
+ useEffect3(() => {
429
+ return onEvent(event, (detail) => {
430
+ handler(detail.payload, detail.sourceAppId);
431
+ });
432
+ }, [event, handler]);
433
+ }
434
+ export {
435
+ useVibeLoader,
436
+ useVibeEvents,
437
+ useVibeBridge,
438
+ getEventBus,
439
+ filterByPermissions,
440
+ emitEvent,
441
+ createToastAdapter,
442
+ createThemeAdapter,
443
+ createStorageAdapter,
444
+ createNavigationAdapter,
445
+ createEventsAdapter,
446
+ createAuthAdapter,
447
+ createApiAdapter,
448
+ VibeHost,
449
+ VibeErrorBoundary
450
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiworkbench/vibe-bridge",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "publishConfig": { "access": "public" },
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -16,11 +16,12 @@
16
16
  "build": "bun build ./src/index.ts --outdir ./dist --target=browser --external react --external react-dom --external next --external next-auth --external next-auth/react --external next/navigation --external sonner && tsc --emitDeclarationOnly",
17
17
  "dev": "tsc --watch --emitDeclarationOnly",
18
18
  "type-check": "tsc --noEmit",
19
- "clean": "rm -rf dist"
19
+ "clean": "rm -rf dist",
20
+ "prepublishOnly": "bun run build"
20
21
  },
21
22
  "files": ["dist", "src"],
22
23
  "dependencies": {
23
- "@aiworkbench/vibe-types": "^0.0.2"
24
+ "@aiworkbench/vibe-types": "^0.0.3"
24
25
  },
25
26
  "peerDependencies": {
26
27
  "react": "^19.0.0",