@proteos/component-sdk 0.30.0 → 0.32.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context.tsx","../src/hooks.ts"],"names":["createContext","MESSAGE_SOURCE","useMemo","useContext","useState","useEffect"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n AccountClient,\n AgentClient,\n DataClient,\n FunctionsClient,\n KnowledgeClient,\n MetaClient,\n StorageClient,\n} from '@proteos/sdk'\nimport { createContext, type ReactNode, useMemo } from 'react'\n\nimport {\n type Envelope,\n MESSAGE_SOURCE,\n type NavigateMessage,\n type OpenPeekMessage,\n type PageContext,\n} from './protocol'\n\n/** Options for {@link RuntimeContextValue.navigate}. */\nexport interface NavigateOptions {\n /** Open the target in a peek (slide-over) panel instead of full-page. */\n peek?: boolean\n}\n\n/**\n * The authenticated `@proteos/sdk` clients the runtime injects. Same instances\n * the host app uses — pre-wired with a refreshing bearer token, so a component\n * never touches auth headers.\n */\nexport interface ComponentSdk {\n account: AccountClient\n agents: AgentClient\n data: DataClient\n functions: FunctionsClient\n knowledge: KnowledgeClient\n meta: MetaClient\n storage: StorageClient\n}\n\n/**\n * The raw runtime payload the shell hands a component at INIT. The shell builds\n * this; component authors read it through the hooks.\n */\nexport interface RuntimeValue {\n /**\n * The injected sdk clients. On an authenticated page these are the full,\n * bearer-wired clients. On a PUBLIC page (`isPublic: true`) only\n * `functions.actions.invokePublic` reaches the platform — every other\n * client throws on use (there is no token, and the server rejects\n * unauthenticated calls anyway).\n */\n sdk: ComponentSdk\n /** Liquid-resolved props (a snapshot — not a live binding). */\n props: Record<string, unknown>\n /** Page context snapshot: the host record, entity, and URL params. */\n pageCtx: PageContext\n /** API origin SDK calls + asset URLs resolve against. */\n apiBaseUrl: string\n /** Current bearer token getter (escape hatch for raw fetches). Returns ''\n * on public pages. */\n getToken: () => string\n /** True when rendering on an unauthenticated public page. */\n isPublic?: boolean\n /** Org id, set in public mode (public API routes carry it in the path). */\n orgId?: string\n}\n\n/** Runtime value plus the derived helpers the hooks expose. */\nexport interface RuntimeContextValue extends RuntimeValue {\n /** Navigate the host SPA to an in-app path (posts a NAVIGATE message), or\n * open it in a peek panel with `{ peek: true }` (posts OPEN_PEEK). */\n navigate: (to: string, options?: NavigateOptions) => void\n}\n\nexport const RuntimeContext = createContext<RuntimeContextValue | null>(null)\n\n/** Post a NAVIGATE envelope to the host. The host only honours relative,\n * in-app targets (it ignores absolute/external URLs). */\nfunction postNavigate(to: string): void {\n const envelope: Envelope<NavigateMessage> = { source: MESSAGE_SOURCE, type: 'NAVIGATE', to }\n window.parent?.postMessage(envelope, '*')\n}\n\n/** Post an OPEN_PEEK envelope to the host — open the in-app path in a peek\n * panel. Same relative-path contract as {@link postNavigate}. */\nfunction postOpenPeek(to: string): void {\n const envelope: Envelope<OpenPeekMessage> = { source: MESSAGE_SOURCE, type: 'OPEN_PEEK', to }\n window.parent?.postMessage(envelope, '*')\n}\n\n/** Navigate full-page (default) or into a peek panel (`{ peek: true }`). */\nfunction navigate(to: string, options?: NavigateOptions): void {\n if (options?.peek) postOpenPeek(to)\n else postNavigate(to)\n}\n\n/**\n * Provides the runtime value + derived helpers to a component subtree. Mounted\n * by the component-runtime shell around the loaded component — authors never\n * render this themselves. Lives in `@proteos/component-sdk` (a shared,\n * import-mapped singleton) so the context the shell provides is the very same\n * context the component's hooks read, across the bundle boundary.\n */\nexport function RuntimeProvider({ value, children }: { value: RuntimeValue; children: ReactNode }) {\n // The shell builds `value` once at INIT (a stable state object — clients,\n // props and pageCtx are all set once), so memoizing on its identity recreates\n // the context only when the runtime genuinely re-inits.\n const ctx = useMemo<RuntimeContextValue>(() => ({ ...value, navigate }), [value])\n return <RuntimeContext.Provider value={ctx}>{children}</RuntimeContext.Provider>\n}\n","import { useContext, useEffect, useState } from 'react'\n\nimport {\n type ComponentSdk,\n type NavigateOptions,\n RuntimeContext,\n type RuntimeContextValue,\n} from './context'\nimport type { PageContext } from './protocol'\n\n/**\n * Low-level escape hatch: the whole runtime context (sdk, props, pageCtx,\n * apiBaseUrl, getToken, navigate). Prefer the focused hooks below. Throws a\n * clear error if used outside the component runtime.\n */\nexport function useRuntime(): RuntimeContextValue {\n const ctx = useContext(RuntimeContext)\n if (!ctx) {\n throw new Error(\n '@proteos/component-sdk: hooks must run inside the Proteos component runtime. ' +\n 'This usually means the component is rendered outside its iframe, or a ' +\n 'second copy of @proteos/component-sdk was bundled instead of using the ' +\n 'runtime-provided one (keep it external).',\n )\n }\n return ctx\n}\n\n/** The authenticated SDK clients (account / data / functions / meta). */\nexport function useSdk(): ComponentSdk {\n return useRuntime().sdk\n}\n\n/** The component's Liquid-resolved props (a snapshot, not a live binding). */\nexport function useProps<T extends Record<string, unknown> = Record<string, unknown>>(): T {\n return useRuntime().props as T\n}\n\n/**\n * The full page context: host `record`, `entity`, and URL `params`. The\n * `record` is a snapshot taken at mount (`undefined` on record-less platform\n * pages) — fetch via `useSdk().data` for anything that must stay fresh.\n */\nexport function usePageContext(): PageContext {\n return useRuntime().pageCtx\n}\n\n/**\n * Navigate the host SPA to an in-app path, e.g.\n * `navigate('/org/acme/record/task/123')`. The host ignores absolute/external\n * URLs. Build org/app-prefixed paths with `useHostLocation().appBasePath`.\n *\n * Pass `{ peek: true }` to open the path in a peek (slide-over) panel instead\n * of full-page navigation — e.g. `navigate(path, { peek: true })`. The host\n * peeks what it can (today: platform pages) and falls back to full navigation.\n */\nexport function useNavigate(): (to: string, options?: NavigateOptions) => void {\n return useRuntime().navigate\n}\n\n/** The API origin SDK calls resolve against (for building raw asset URLs). */\nexport function useApiBaseUrl(): string {\n return useRuntime().apiBaseUrl\n}\n\n/**\n * A getter for the current bearer token. Returns a function (not the token)\n * because the token is refreshed in place — read it at call time for a raw\n * `fetch`. Most components never need this; prefer `useSdk()`.\n */\nexport function useAuthToken(): () => string {\n return useRuntime().getToken\n}\n\nexport interface HostLocation {\n /** The host tab's pathname (same-origin read), or null if unavailable. */\n pathname: string | null\n /** The org id parsed from `/org/<orgId>/…`, or null. */\n orgId: string | null\n /** The `/org/<orgId>/app/<appId>` prefix, or null when not on an app page. */\n appBasePath: string | null\n}\n\nfunction readHostLocation(): HostLocation {\n const empty: HostLocation = { pathname: null, orgId: null, appBasePath: null }\n try {\n const parentWindow = window.parent\n if (!parentWindow || parentWindow === window) return empty\n const pathname = parentWindow.location.pathname\n const appMatch = pathname.match(/^\\/org\\/[^/]+\\/app\\/[^/]+/)\n const orgMatch = pathname.match(/^\\/org\\/([^/]+)\\//)\n return {\n pathname,\n orgId: orgMatch ? (orgMatch[1] ?? null) : null,\n appBasePath: appMatch ? appMatch[0] : null,\n }\n } catch {\n // Cross-origin (untrusted-component future) or detached — fall back to null.\n return empty\n }\n}\n\n/**\n * Read the host tab's location (same-origin) — the org id and `/org/.../app/...`\n * prefix needed to build navigation targets on platform pages. Read once on\n * mount (the iframe re-inits when the host route changes).\n */\nexport function useHostLocation(): HostLocation {\n const [loc] = useState(readHostLocation)\n return loc\n}\n\nexport interface FillViewportOptions {\n /** Gap left below the component (px). Default 24. */\n bottomMargin?: number\n /** Floor for the computed height (px). Default 320. */\n minHeight?: number\n}\n\n/**\n * Compute a \"fill the rest of the viewport\" height for full-bleed layouts\n * (boards, canvases). The runtime auto-sizes the iframe to its content, so a\n * component can't use its own `vh` units (circular). The iframe is same-origin,\n * so this measures the parent viewport minus the iframe's offset instead.\n * Returns `null` when it can't measure (fall back to natural height).\n */\nexport function useFillViewportHeight(options: FillViewportOptions = {}): number | null {\n const { bottomMargin = 24, minHeight = 320 } = options\n const [height, setHeight] = useState<number | null>(null)\n\n useEffect(() => {\n function compute(): void {\n try {\n const frame = window.frameElement\n const parentWindow = window.parent\n if (!frame || !parentWindow || parentWindow === window) return\n const available =\n parentWindow.innerHeight - frame.getBoundingClientRect().top - bottomMargin\n setHeight(Math.max(available, minHeight))\n } catch {\n setHeight(null) // cross-origin or detached — fall back to natural height\n }\n }\n compute()\n try {\n window.parent.addEventListener('resize', compute)\n return () => window.parent.removeEventListener('resize', compute)\n } catch {\n return\n }\n }, [bottomMargin, minHeight])\n\n return height\n}\n"]}
1
+ {"version":3,"sources":["../src/context.tsx","../src/hooks.ts"],"names":["createContext","MESSAGE_SOURCE","useMemo","useContext","useState","useEffect"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n AccountClient,\n AgentClient,\n ConversationClient,\n DataClient,\n FunctionsClient,\n KnowledgeClient,\n MetaClient,\n StorageClient,\n} from '@proteos/sdk'\nimport { createContext, type ReactNode, useMemo } from 'react'\n\nimport {\n type Envelope,\n MESSAGE_SOURCE,\n type NavigateMessage,\n type OpenPeekMessage,\n type PageContext,\n} from './protocol'\n\n/** Options for {@link RuntimeContextValue.navigate}. */\nexport interface NavigateOptions {\n /** Open the target in a peek (slide-over) panel instead of full-page. */\n peek?: boolean\n}\n\n/**\n * The authenticated `@proteos/sdk` clients the runtime injects. Same instances\n * the host app uses — pre-wired with a refreshing bearer token, so a component\n * never touches auth headers.\n */\nexport interface ComponentSdk {\n account: AccountClient\n agents: AgentClient\n /**\n * Conversations, messages, contacts, connections (conversation-service) —\n * e.g. the DraftMessageComposer review surface. Plural per the platform's\n * resource-naming rule; the web app's own `useSdk().conversation` predates\n * it (documented asymmetry).\n */\n conversations: ConversationClient\n data: DataClient\n functions: FunctionsClient\n knowledge: KnowledgeClient\n meta: MetaClient\n storage: StorageClient\n}\n\n/**\n * The raw runtime payload the shell hands a component at INIT. The shell builds\n * this; component authors read it through the hooks.\n */\nexport interface RuntimeValue {\n /**\n * The injected sdk clients. On an authenticated page these are the full,\n * bearer-wired clients. On a PUBLIC page (`isPublic: true`) only\n * `functions.actions.invokePublic` reaches the platform — every other\n * client throws on use (there is no token, and the server rejects\n * unauthenticated calls anyway).\n */\n sdk: ComponentSdk\n /** Liquid-resolved props (a snapshot — not a live binding). */\n props: Record<string, unknown>\n /** Page context snapshot: the host record, entity, and URL params. */\n pageCtx: PageContext\n /** API origin SDK calls + asset URLs resolve against. */\n apiBaseUrl: string\n /** Current bearer token getter (escape hatch for raw fetches). Returns ''\n * on public pages. */\n getToken: () => string\n /** True when rendering on an unauthenticated public page. */\n isPublic?: boolean\n /** Org id, set in public mode (public API routes carry it in the path). */\n orgId?: string\n}\n\n/** Runtime value plus the derived helpers the hooks expose. */\nexport interface RuntimeContextValue extends RuntimeValue {\n /** Navigate the host SPA to an in-app path (posts a NAVIGATE message), or\n * open it in a peek panel with `{ peek: true }` (posts OPEN_PEEK). */\n navigate: (to: string, options?: NavigateOptions) => void\n}\n\nexport const RuntimeContext = createContext<RuntimeContextValue | null>(null)\n\n/** Post a NAVIGATE envelope to the host. The host only honours relative,\n * in-app targets (it ignores absolute/external URLs). */\nfunction postNavigate(to: string): void {\n const envelope: Envelope<NavigateMessage> = { source: MESSAGE_SOURCE, type: 'NAVIGATE', to }\n window.parent?.postMessage(envelope, '*')\n}\n\n/** Post an OPEN_PEEK envelope to the host — open the in-app path in a peek\n * panel. Same relative-path contract as {@link postNavigate}. */\nfunction postOpenPeek(to: string): void {\n const envelope: Envelope<OpenPeekMessage> = { source: MESSAGE_SOURCE, type: 'OPEN_PEEK', to }\n window.parent?.postMessage(envelope, '*')\n}\n\n/** Navigate full-page (default) or into a peek panel (`{ peek: true }`). */\nfunction navigate(to: string, options?: NavigateOptions): void {\n if (options?.peek) postOpenPeek(to)\n else postNavigate(to)\n}\n\n/**\n * Provides the runtime value + derived helpers to a component subtree. Mounted\n * by the component-runtime shell around the loaded component — authors never\n * render this themselves. Lives in `@proteos/component-sdk` (a shared,\n * import-mapped singleton) so the context the shell provides is the very same\n * context the component's hooks read, across the bundle boundary.\n */\nexport function RuntimeProvider({ value, children }: { value: RuntimeValue; children: ReactNode }) {\n // The shell builds `value` once at INIT (a stable state object — clients,\n // props and pageCtx are all set once), so memoizing on its identity recreates\n // the context only when the runtime genuinely re-inits.\n const ctx = useMemo<RuntimeContextValue>(() => ({ ...value, navigate }), [value])\n return <RuntimeContext.Provider value={ctx}>{children}</RuntimeContext.Provider>\n}\n","import { useContext, useEffect, useState } from 'react'\n\nimport {\n type ComponentSdk,\n type NavigateOptions,\n RuntimeContext,\n type RuntimeContextValue,\n} from './context'\nimport type { PageContext } from './protocol'\n\n/**\n * Low-level escape hatch: the whole runtime context (sdk, props, pageCtx,\n * apiBaseUrl, getToken, navigate). Prefer the focused hooks below. Throws a\n * clear error if used outside the component runtime.\n */\nexport function useRuntime(): RuntimeContextValue {\n const ctx = useContext(RuntimeContext)\n if (!ctx) {\n throw new Error(\n '@proteos/component-sdk: hooks must run inside the Proteos component runtime. ' +\n 'This usually means the component is rendered outside its iframe, or a ' +\n 'second copy of @proteos/component-sdk was bundled instead of using the ' +\n 'runtime-provided one (keep it external).',\n )\n }\n return ctx\n}\n\n/** The authenticated SDK clients (account / agents / conversations / data / functions / knowledge / meta / storage). */\nexport function useSdk(): ComponentSdk {\n return useRuntime().sdk\n}\n\n/** The component's Liquid-resolved props (a snapshot, not a live binding). */\nexport function useProps<T extends Record<string, unknown> = Record<string, unknown>>(): T {\n return useRuntime().props as T\n}\n\n/**\n * The full page context: host `record`, `entity`, and URL `params`. The\n * `record` is a snapshot taken at mount (`undefined` on record-less platform\n * pages) — fetch via `useSdk().data` for anything that must stay fresh.\n */\nexport function usePageContext(): PageContext {\n return useRuntime().pageCtx\n}\n\n/**\n * Navigate the host SPA to an in-app path, e.g.\n * `navigate('/org/acme/record/task/123')`. The host ignores absolute/external\n * URLs. Build org/app-prefixed paths with `useHostLocation().appBasePath`.\n *\n * Pass `{ peek: true }` to open the path in a peek (slide-over) panel instead\n * of full-page navigation — e.g. `navigate(path, { peek: true })`. The host\n * peeks what it can (today: platform pages) and falls back to full navigation.\n */\nexport function useNavigate(): (to: string, options?: NavigateOptions) => void {\n return useRuntime().navigate\n}\n\n/** The API origin SDK calls resolve against (for building raw asset URLs). */\nexport function useApiBaseUrl(): string {\n return useRuntime().apiBaseUrl\n}\n\n/**\n * A getter for the current bearer token. Returns a function (not the token)\n * because the token is refreshed in place — read it at call time for a raw\n * `fetch`. Most components never need this; prefer `useSdk()`.\n */\nexport function useAuthToken(): () => string {\n return useRuntime().getToken\n}\n\nexport interface HostLocation {\n /** The host tab's pathname (same-origin read), or null if unavailable. */\n pathname: string | null\n /** The org id parsed from `/org/<orgId>/…`, or null. */\n orgId: string | null\n /** The `/org/<orgId>/app/<appId>` prefix, or null when not on an app page. */\n appBasePath: string | null\n}\n\nfunction readHostLocation(): HostLocation {\n const empty: HostLocation = { pathname: null, orgId: null, appBasePath: null }\n try {\n const parentWindow = window.parent\n if (!parentWindow || parentWindow === window) return empty\n const pathname = parentWindow.location.pathname\n const appMatch = pathname.match(/^\\/org\\/[^/]+\\/app\\/[^/]+/)\n const orgMatch = pathname.match(/^\\/org\\/([^/]+)\\//)\n return {\n pathname,\n orgId: orgMatch ? (orgMatch[1] ?? null) : null,\n appBasePath: appMatch ? appMatch[0] : null,\n }\n } catch {\n // Cross-origin (untrusted-component future) or detached — fall back to null.\n return empty\n }\n}\n\n/**\n * Read the host tab's location (same-origin) — the org id and `/org/.../app/...`\n * prefix needed to build navigation targets on platform pages. Read once on\n * mount (the iframe re-inits when the host route changes).\n */\nexport function useHostLocation(): HostLocation {\n const [loc] = useState(readHostLocation)\n return loc\n}\n\nexport interface FillViewportOptions {\n /** Gap left below the component (px). Default 24. */\n bottomMargin?: number\n /** Floor for the computed height (px). Default 320. */\n minHeight?: number\n}\n\n/**\n * Compute a \"fill the rest of the viewport\" height for full-bleed layouts\n * (boards, canvases). The runtime auto-sizes the iframe to its content, so a\n * component can't use its own `vh` units (circular). The iframe is same-origin,\n * so this measures the parent viewport minus the iframe's offset instead.\n * Returns `null` when it can't measure (fall back to natural height).\n */\nexport function useFillViewportHeight(options: FillViewportOptions = {}): number | null {\n const { bottomMargin = 24, minHeight = 320 } = options\n const [height, setHeight] = useState<number | null>(null)\n\n useEffect(() => {\n function compute(): void {\n try {\n const frame = window.frameElement\n const parentWindow = window.parent\n if (!frame || !parentWindow || parentWindow === window) return\n const available =\n parentWindow.innerHeight - frame.getBoundingClientRect().top - bottomMargin\n setHeight(Math.max(available, minHeight))\n } catch {\n setHeight(null) // cross-origin or detached — fall back to natural height\n }\n }\n compute()\n try {\n window.parent.addEventListener('resize', compute)\n return () => window.parent.removeEventListener('resize', compute)\n } catch {\n return\n }\n }, [bottomMargin, minHeight])\n\n return height\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { AccountClient, AgentClient, DataClient, FunctionsClient, KnowledgeClient, MetaClient, StorageClient } from '@proteos/sdk';
3
+ import { AccountClient, AgentClient, ConversationClient, DataClient, FunctionsClient, KnowledgeClient, MetaClient, StorageClient } from '@proteos/sdk';
4
4
  import { PageContext } from './protocol.cjs';
5
5
  export { AuthRefreshMessage, DataInvalidateMessage, Envelope, ErrorMessage, HostMessage, InitMessage, MESSAGE_SOURCE, NavigateMessage, OpenPeekMessage, ReadyMessage, ResizeMessage, RuntimeMessage, isHostMessage, isRuntimeMessage } from './protocol.cjs';
6
6
 
@@ -17,6 +17,13 @@ interface NavigateOptions {
17
17
  interface ComponentSdk {
18
18
  account: AccountClient;
19
19
  agents: AgentClient;
20
+ /**
21
+ * Conversations, messages, contacts, connections (conversation-service) —
22
+ * e.g. the DraftMessageComposer review surface. Plural per the platform's
23
+ * resource-naming rule; the web app's own `useSdk().conversation` predates
24
+ * it (documented asymmetry).
25
+ */
26
+ conversations: ConversationClient;
20
27
  data: DataClient;
21
28
  functions: FunctionsClient;
22
29
  knowledge: KnowledgeClient;
@@ -86,7 +93,7 @@ declare global {
86
93
  * clear error if used outside the component runtime.
87
94
  */
88
95
  declare function useRuntime(): RuntimeContextValue;
89
- /** The authenticated SDK clients (account / data / functions / meta). */
96
+ /** The authenticated SDK clients (account / agents / conversations / data / functions / knowledge / meta / storage). */
90
97
  declare function useSdk(): ComponentSdk;
91
98
  /** The component's Liquid-resolved props (a snapshot, not a live binding). */
92
99
  declare function useProps<T extends Record<string, unknown> = Record<string, unknown>>(): T;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { AccountClient, AgentClient, DataClient, FunctionsClient, KnowledgeClient, MetaClient, StorageClient } from '@proteos/sdk';
3
+ import { AccountClient, AgentClient, ConversationClient, DataClient, FunctionsClient, KnowledgeClient, MetaClient, StorageClient } from '@proteos/sdk';
4
4
  import { PageContext } from './protocol.js';
5
5
  export { AuthRefreshMessage, DataInvalidateMessage, Envelope, ErrorMessage, HostMessage, InitMessage, MESSAGE_SOURCE, NavigateMessage, OpenPeekMessage, ReadyMessage, ResizeMessage, RuntimeMessage, isHostMessage, isRuntimeMessage } from './protocol.js';
6
6
 
@@ -17,6 +17,13 @@ interface NavigateOptions {
17
17
  interface ComponentSdk {
18
18
  account: AccountClient;
19
19
  agents: AgentClient;
20
+ /**
21
+ * Conversations, messages, contacts, connections (conversation-service) —
22
+ * e.g. the DraftMessageComposer review surface. Plural per the platform's
23
+ * resource-naming rule; the web app's own `useSdk().conversation` predates
24
+ * it (documented asymmetry).
25
+ */
26
+ conversations: ConversationClient;
20
27
  data: DataClient;
21
28
  functions: FunctionsClient;
22
29
  knowledge: KnowledgeClient;
@@ -86,7 +93,7 @@ declare global {
86
93
  * clear error if used outside the component runtime.
87
94
  */
88
95
  declare function useRuntime(): RuntimeContextValue;
89
- /** The authenticated SDK clients (account / data / functions / meta). */
96
+ /** The authenticated SDK clients (account / agents / conversations / data / functions / knowledge / meta / storage). */
90
97
  declare function useSdk(): ComponentSdk;
91
98
  /** The component's Liquid-resolved props (a snapshot, not a live binding). */
92
99
  declare function useProps<T extends Record<string, unknown> = Record<string, unknown>>(): T;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context.tsx","../src/hooks.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\n AccountClient,\n AgentClient,\n DataClient,\n FunctionsClient,\n KnowledgeClient,\n MetaClient,\n StorageClient,\n} from '@proteos/sdk'\nimport { createContext, type ReactNode, useMemo } from 'react'\n\nimport {\n type Envelope,\n MESSAGE_SOURCE,\n type NavigateMessage,\n type OpenPeekMessage,\n type PageContext,\n} from './protocol'\n\n/** Options for {@link RuntimeContextValue.navigate}. */\nexport interface NavigateOptions {\n /** Open the target in a peek (slide-over) panel instead of full-page. */\n peek?: boolean\n}\n\n/**\n * The authenticated `@proteos/sdk` clients the runtime injects. Same instances\n * the host app uses — pre-wired with a refreshing bearer token, so a component\n * never touches auth headers.\n */\nexport interface ComponentSdk {\n account: AccountClient\n agents: AgentClient\n data: DataClient\n functions: FunctionsClient\n knowledge: KnowledgeClient\n meta: MetaClient\n storage: StorageClient\n}\n\n/**\n * The raw runtime payload the shell hands a component at INIT. The shell builds\n * this; component authors read it through the hooks.\n */\nexport interface RuntimeValue {\n /**\n * The injected sdk clients. On an authenticated page these are the full,\n * bearer-wired clients. On a PUBLIC page (`isPublic: true`) only\n * `functions.actions.invokePublic` reaches the platform — every other\n * client throws on use (there is no token, and the server rejects\n * unauthenticated calls anyway).\n */\n sdk: ComponentSdk\n /** Liquid-resolved props (a snapshot — not a live binding). */\n props: Record<string, unknown>\n /** Page context snapshot: the host record, entity, and URL params. */\n pageCtx: PageContext\n /** API origin SDK calls + asset URLs resolve against. */\n apiBaseUrl: string\n /** Current bearer token getter (escape hatch for raw fetches). Returns ''\n * on public pages. */\n getToken: () => string\n /** True when rendering on an unauthenticated public page. */\n isPublic?: boolean\n /** Org id, set in public mode (public API routes carry it in the path). */\n orgId?: string\n}\n\n/** Runtime value plus the derived helpers the hooks expose. */\nexport interface RuntimeContextValue extends RuntimeValue {\n /** Navigate the host SPA to an in-app path (posts a NAVIGATE message), or\n * open it in a peek panel with `{ peek: true }` (posts OPEN_PEEK). */\n navigate: (to: string, options?: NavigateOptions) => void\n}\n\nexport const RuntimeContext = createContext<RuntimeContextValue | null>(null)\n\n/** Post a NAVIGATE envelope to the host. The host only honours relative,\n * in-app targets (it ignores absolute/external URLs). */\nfunction postNavigate(to: string): void {\n const envelope: Envelope<NavigateMessage> = { source: MESSAGE_SOURCE, type: 'NAVIGATE', to }\n window.parent?.postMessage(envelope, '*')\n}\n\n/** Post an OPEN_PEEK envelope to the host — open the in-app path in a peek\n * panel. Same relative-path contract as {@link postNavigate}. */\nfunction postOpenPeek(to: string): void {\n const envelope: Envelope<OpenPeekMessage> = { source: MESSAGE_SOURCE, type: 'OPEN_PEEK', to }\n window.parent?.postMessage(envelope, '*')\n}\n\n/** Navigate full-page (default) or into a peek panel (`{ peek: true }`). */\nfunction navigate(to: string, options?: NavigateOptions): void {\n if (options?.peek) postOpenPeek(to)\n else postNavigate(to)\n}\n\n/**\n * Provides the runtime value + derived helpers to a component subtree. Mounted\n * by the component-runtime shell around the loaded component — authors never\n * render this themselves. Lives in `@proteos/component-sdk` (a shared,\n * import-mapped singleton) so the context the shell provides is the very same\n * context the component's hooks read, across the bundle boundary.\n */\nexport function RuntimeProvider({ value, children }: { value: RuntimeValue; children: ReactNode }) {\n // The shell builds `value` once at INIT (a stable state object — clients,\n // props and pageCtx are all set once), so memoizing on its identity recreates\n // the context only when the runtime genuinely re-inits.\n const ctx = useMemo<RuntimeContextValue>(() => ({ ...value, navigate }), [value])\n return <RuntimeContext.Provider value={ctx}>{children}</RuntimeContext.Provider>\n}\n","import { useContext, useEffect, useState } from 'react'\n\nimport {\n type ComponentSdk,\n type NavigateOptions,\n RuntimeContext,\n type RuntimeContextValue,\n} from './context'\nimport type { PageContext } from './protocol'\n\n/**\n * Low-level escape hatch: the whole runtime context (sdk, props, pageCtx,\n * apiBaseUrl, getToken, navigate). Prefer the focused hooks below. Throws a\n * clear error if used outside the component runtime.\n */\nexport function useRuntime(): RuntimeContextValue {\n const ctx = useContext(RuntimeContext)\n if (!ctx) {\n throw new Error(\n '@proteos/component-sdk: hooks must run inside the Proteos component runtime. ' +\n 'This usually means the component is rendered outside its iframe, or a ' +\n 'second copy of @proteos/component-sdk was bundled instead of using the ' +\n 'runtime-provided one (keep it external).',\n )\n }\n return ctx\n}\n\n/** The authenticated SDK clients (account / data / functions / meta). */\nexport function useSdk(): ComponentSdk {\n return useRuntime().sdk\n}\n\n/** The component's Liquid-resolved props (a snapshot, not a live binding). */\nexport function useProps<T extends Record<string, unknown> = Record<string, unknown>>(): T {\n return useRuntime().props as T\n}\n\n/**\n * The full page context: host `record`, `entity`, and URL `params`. The\n * `record` is a snapshot taken at mount (`undefined` on record-less platform\n * pages) — fetch via `useSdk().data` for anything that must stay fresh.\n */\nexport function usePageContext(): PageContext {\n return useRuntime().pageCtx\n}\n\n/**\n * Navigate the host SPA to an in-app path, e.g.\n * `navigate('/org/acme/record/task/123')`. The host ignores absolute/external\n * URLs. Build org/app-prefixed paths with `useHostLocation().appBasePath`.\n *\n * Pass `{ peek: true }` to open the path in a peek (slide-over) panel instead\n * of full-page navigation — e.g. `navigate(path, { peek: true })`. The host\n * peeks what it can (today: platform pages) and falls back to full navigation.\n */\nexport function useNavigate(): (to: string, options?: NavigateOptions) => void {\n return useRuntime().navigate\n}\n\n/** The API origin SDK calls resolve against (for building raw asset URLs). */\nexport function useApiBaseUrl(): string {\n return useRuntime().apiBaseUrl\n}\n\n/**\n * A getter for the current bearer token. Returns a function (not the token)\n * because the token is refreshed in place — read it at call time for a raw\n * `fetch`. Most components never need this; prefer `useSdk()`.\n */\nexport function useAuthToken(): () => string {\n return useRuntime().getToken\n}\n\nexport interface HostLocation {\n /** The host tab's pathname (same-origin read), or null if unavailable. */\n pathname: string | null\n /** The org id parsed from `/org/<orgId>/…`, or null. */\n orgId: string | null\n /** The `/org/<orgId>/app/<appId>` prefix, or null when not on an app page. */\n appBasePath: string | null\n}\n\nfunction readHostLocation(): HostLocation {\n const empty: HostLocation = { pathname: null, orgId: null, appBasePath: null }\n try {\n const parentWindow = window.parent\n if (!parentWindow || parentWindow === window) return empty\n const pathname = parentWindow.location.pathname\n const appMatch = pathname.match(/^\\/org\\/[^/]+\\/app\\/[^/]+/)\n const orgMatch = pathname.match(/^\\/org\\/([^/]+)\\//)\n return {\n pathname,\n orgId: orgMatch ? (orgMatch[1] ?? null) : null,\n appBasePath: appMatch ? appMatch[0] : null,\n }\n } catch {\n // Cross-origin (untrusted-component future) or detached — fall back to null.\n return empty\n }\n}\n\n/**\n * Read the host tab's location (same-origin) — the org id and `/org/.../app/...`\n * prefix needed to build navigation targets on platform pages. Read once on\n * mount (the iframe re-inits when the host route changes).\n */\nexport function useHostLocation(): HostLocation {\n const [loc] = useState(readHostLocation)\n return loc\n}\n\nexport interface FillViewportOptions {\n /** Gap left below the component (px). Default 24. */\n bottomMargin?: number\n /** Floor for the computed height (px). Default 320. */\n minHeight?: number\n}\n\n/**\n * Compute a \"fill the rest of the viewport\" height for full-bleed layouts\n * (boards, canvases). The runtime auto-sizes the iframe to its content, so a\n * component can't use its own `vh` units (circular). The iframe is same-origin,\n * so this measures the parent viewport minus the iframe's offset instead.\n * Returns `null` when it can't measure (fall back to natural height).\n */\nexport function useFillViewportHeight(options: FillViewportOptions = {}): number | null {\n const { bottomMargin = 24, minHeight = 320 } = options\n const [height, setHeight] = useState<number | null>(null)\n\n useEffect(() => {\n function compute(): void {\n try {\n const frame = window.frameElement\n const parentWindow = window.parent\n if (!frame || !parentWindow || parentWindow === window) return\n const available =\n parentWindow.innerHeight - frame.getBoundingClientRect().top - bottomMargin\n setHeight(Math.max(available, minHeight))\n } catch {\n setHeight(null) // cross-origin or detached — fall back to natural height\n }\n }\n compute()\n try {\n window.parent.addEventListener('resize', compute)\n return () => window.parent.removeEventListener('resize', compute)\n } catch {\n return\n }\n }, [bottomMargin, minHeight])\n\n return height\n}\n"]}
1
+ {"version":3,"sources":["../src/context.tsx","../src/hooks.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\n AccountClient,\n AgentClient,\n ConversationClient,\n DataClient,\n FunctionsClient,\n KnowledgeClient,\n MetaClient,\n StorageClient,\n} from '@proteos/sdk'\nimport { createContext, type ReactNode, useMemo } from 'react'\n\nimport {\n type Envelope,\n MESSAGE_SOURCE,\n type NavigateMessage,\n type OpenPeekMessage,\n type PageContext,\n} from './protocol'\n\n/** Options for {@link RuntimeContextValue.navigate}. */\nexport interface NavigateOptions {\n /** Open the target in a peek (slide-over) panel instead of full-page. */\n peek?: boolean\n}\n\n/**\n * The authenticated `@proteos/sdk` clients the runtime injects. Same instances\n * the host app uses — pre-wired with a refreshing bearer token, so a component\n * never touches auth headers.\n */\nexport interface ComponentSdk {\n account: AccountClient\n agents: AgentClient\n /**\n * Conversations, messages, contacts, connections (conversation-service) —\n * e.g. the DraftMessageComposer review surface. Plural per the platform's\n * resource-naming rule; the web app's own `useSdk().conversation` predates\n * it (documented asymmetry).\n */\n conversations: ConversationClient\n data: DataClient\n functions: FunctionsClient\n knowledge: KnowledgeClient\n meta: MetaClient\n storage: StorageClient\n}\n\n/**\n * The raw runtime payload the shell hands a component at INIT. The shell builds\n * this; component authors read it through the hooks.\n */\nexport interface RuntimeValue {\n /**\n * The injected sdk clients. On an authenticated page these are the full,\n * bearer-wired clients. On a PUBLIC page (`isPublic: true`) only\n * `functions.actions.invokePublic` reaches the platform — every other\n * client throws on use (there is no token, and the server rejects\n * unauthenticated calls anyway).\n */\n sdk: ComponentSdk\n /** Liquid-resolved props (a snapshot — not a live binding). */\n props: Record<string, unknown>\n /** Page context snapshot: the host record, entity, and URL params. */\n pageCtx: PageContext\n /** API origin SDK calls + asset URLs resolve against. */\n apiBaseUrl: string\n /** Current bearer token getter (escape hatch for raw fetches). Returns ''\n * on public pages. */\n getToken: () => string\n /** True when rendering on an unauthenticated public page. */\n isPublic?: boolean\n /** Org id, set in public mode (public API routes carry it in the path). */\n orgId?: string\n}\n\n/** Runtime value plus the derived helpers the hooks expose. */\nexport interface RuntimeContextValue extends RuntimeValue {\n /** Navigate the host SPA to an in-app path (posts a NAVIGATE message), or\n * open it in a peek panel with `{ peek: true }` (posts OPEN_PEEK). */\n navigate: (to: string, options?: NavigateOptions) => void\n}\n\nexport const RuntimeContext = createContext<RuntimeContextValue | null>(null)\n\n/** Post a NAVIGATE envelope to the host. The host only honours relative,\n * in-app targets (it ignores absolute/external URLs). */\nfunction postNavigate(to: string): void {\n const envelope: Envelope<NavigateMessage> = { source: MESSAGE_SOURCE, type: 'NAVIGATE', to }\n window.parent?.postMessage(envelope, '*')\n}\n\n/** Post an OPEN_PEEK envelope to the host — open the in-app path in a peek\n * panel. Same relative-path contract as {@link postNavigate}. */\nfunction postOpenPeek(to: string): void {\n const envelope: Envelope<OpenPeekMessage> = { source: MESSAGE_SOURCE, type: 'OPEN_PEEK', to }\n window.parent?.postMessage(envelope, '*')\n}\n\n/** Navigate full-page (default) or into a peek panel (`{ peek: true }`). */\nfunction navigate(to: string, options?: NavigateOptions): void {\n if (options?.peek) postOpenPeek(to)\n else postNavigate(to)\n}\n\n/**\n * Provides the runtime value + derived helpers to a component subtree. Mounted\n * by the component-runtime shell around the loaded component — authors never\n * render this themselves. Lives in `@proteos/component-sdk` (a shared,\n * import-mapped singleton) so the context the shell provides is the very same\n * context the component's hooks read, across the bundle boundary.\n */\nexport function RuntimeProvider({ value, children }: { value: RuntimeValue; children: ReactNode }) {\n // The shell builds `value` once at INIT (a stable state object — clients,\n // props and pageCtx are all set once), so memoizing on its identity recreates\n // the context only when the runtime genuinely re-inits.\n const ctx = useMemo<RuntimeContextValue>(() => ({ ...value, navigate }), [value])\n return <RuntimeContext.Provider value={ctx}>{children}</RuntimeContext.Provider>\n}\n","import { useContext, useEffect, useState } from 'react'\n\nimport {\n type ComponentSdk,\n type NavigateOptions,\n RuntimeContext,\n type RuntimeContextValue,\n} from './context'\nimport type { PageContext } from './protocol'\n\n/**\n * Low-level escape hatch: the whole runtime context (sdk, props, pageCtx,\n * apiBaseUrl, getToken, navigate). Prefer the focused hooks below. Throws a\n * clear error if used outside the component runtime.\n */\nexport function useRuntime(): RuntimeContextValue {\n const ctx = useContext(RuntimeContext)\n if (!ctx) {\n throw new Error(\n '@proteos/component-sdk: hooks must run inside the Proteos component runtime. ' +\n 'This usually means the component is rendered outside its iframe, or a ' +\n 'second copy of @proteos/component-sdk was bundled instead of using the ' +\n 'runtime-provided one (keep it external).',\n )\n }\n return ctx\n}\n\n/** The authenticated SDK clients (account / agents / conversations / data / functions / knowledge / meta / storage). */\nexport function useSdk(): ComponentSdk {\n return useRuntime().sdk\n}\n\n/** The component's Liquid-resolved props (a snapshot, not a live binding). */\nexport function useProps<T extends Record<string, unknown> = Record<string, unknown>>(): T {\n return useRuntime().props as T\n}\n\n/**\n * The full page context: host `record`, `entity`, and URL `params`. The\n * `record` is a snapshot taken at mount (`undefined` on record-less platform\n * pages) — fetch via `useSdk().data` for anything that must stay fresh.\n */\nexport function usePageContext(): PageContext {\n return useRuntime().pageCtx\n}\n\n/**\n * Navigate the host SPA to an in-app path, e.g.\n * `navigate('/org/acme/record/task/123')`. The host ignores absolute/external\n * URLs. Build org/app-prefixed paths with `useHostLocation().appBasePath`.\n *\n * Pass `{ peek: true }` to open the path in a peek (slide-over) panel instead\n * of full-page navigation — e.g. `navigate(path, { peek: true })`. The host\n * peeks what it can (today: platform pages) and falls back to full navigation.\n */\nexport function useNavigate(): (to: string, options?: NavigateOptions) => void {\n return useRuntime().navigate\n}\n\n/** The API origin SDK calls resolve against (for building raw asset URLs). */\nexport function useApiBaseUrl(): string {\n return useRuntime().apiBaseUrl\n}\n\n/**\n * A getter for the current bearer token. Returns a function (not the token)\n * because the token is refreshed in place — read it at call time for a raw\n * `fetch`. Most components never need this; prefer `useSdk()`.\n */\nexport function useAuthToken(): () => string {\n return useRuntime().getToken\n}\n\nexport interface HostLocation {\n /** The host tab's pathname (same-origin read), or null if unavailable. */\n pathname: string | null\n /** The org id parsed from `/org/<orgId>/…`, or null. */\n orgId: string | null\n /** The `/org/<orgId>/app/<appId>` prefix, or null when not on an app page. */\n appBasePath: string | null\n}\n\nfunction readHostLocation(): HostLocation {\n const empty: HostLocation = { pathname: null, orgId: null, appBasePath: null }\n try {\n const parentWindow = window.parent\n if (!parentWindow || parentWindow === window) return empty\n const pathname = parentWindow.location.pathname\n const appMatch = pathname.match(/^\\/org\\/[^/]+\\/app\\/[^/]+/)\n const orgMatch = pathname.match(/^\\/org\\/([^/]+)\\//)\n return {\n pathname,\n orgId: orgMatch ? (orgMatch[1] ?? null) : null,\n appBasePath: appMatch ? appMatch[0] : null,\n }\n } catch {\n // Cross-origin (untrusted-component future) or detached — fall back to null.\n return empty\n }\n}\n\n/**\n * Read the host tab's location (same-origin) — the org id and `/org/.../app/...`\n * prefix needed to build navigation targets on platform pages. Read once on\n * mount (the iframe re-inits when the host route changes).\n */\nexport function useHostLocation(): HostLocation {\n const [loc] = useState(readHostLocation)\n return loc\n}\n\nexport interface FillViewportOptions {\n /** Gap left below the component (px). Default 24. */\n bottomMargin?: number\n /** Floor for the computed height (px). Default 320. */\n minHeight?: number\n}\n\n/**\n * Compute a \"fill the rest of the viewport\" height for full-bleed layouts\n * (boards, canvases). The runtime auto-sizes the iframe to its content, so a\n * component can't use its own `vh` units (circular). The iframe is same-origin,\n * so this measures the parent viewport minus the iframe's offset instead.\n * Returns `null` when it can't measure (fall back to natural height).\n */\nexport function useFillViewportHeight(options: FillViewportOptions = {}): number | null {\n const { bottomMargin = 24, minHeight = 320 } = options\n const [height, setHeight] = useState<number | null>(null)\n\n useEffect(() => {\n function compute(): void {\n try {\n const frame = window.frameElement\n const parentWindow = window.parent\n if (!frame || !parentWindow || parentWindow === window) return\n const available =\n parentWindow.innerHeight - frame.getBoundingClientRect().top - bottomMargin\n setHeight(Math.max(available, minHeight))\n } catch {\n setHeight(null) // cross-origin or detached — fall back to natural height\n }\n }\n compute()\n try {\n window.parent.addEventListener('resize', compute)\n return () => window.parent.removeEventListener('resize', compute)\n } catch {\n return\n }\n }, [bottomMargin, minHeight])\n\n return height\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proteos/component-sdk",
3
- "version": "0.30.0",
3
+ "version": "0.32.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Typed runtime hooks for authoring Proteos custom components — the SDK you import inside a component bundle.",
6
6
  "repository": {
@@ -42,7 +42,7 @@
42
42
  "src"
43
43
  ],
44
44
  "dependencies": {
45
- "@proteos/sdk": "^0.30.0"
45
+ "@proteos/sdk": "^0.32.0"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "@tanstack/react-query": ">=5.0.0",
package/src/context.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  AccountClient,
3
3
  AgentClient,
4
+ ConversationClient,
4
5
  DataClient,
5
6
  FunctionsClient,
6
7
  KnowledgeClient,
@@ -31,6 +32,13 @@ export interface NavigateOptions {
31
32
  export interface ComponentSdk {
32
33
  account: AccountClient
33
34
  agents: AgentClient
35
+ /**
36
+ * Conversations, messages, contacts, connections (conversation-service) —
37
+ * e.g. the DraftMessageComposer review surface. Plural per the platform's
38
+ * resource-naming rule; the web app's own `useSdk().conversation` predates
39
+ * it (documented asymmetry).
40
+ */
41
+ conversations: ConversationClient
34
42
  data: DataClient
35
43
  functions: FunctionsClient
36
44
  knowledge: KnowledgeClient
package/src/hooks.ts CHANGED
@@ -26,7 +26,7 @@ export function useRuntime(): RuntimeContextValue {
26
26
  return ctx
27
27
  }
28
28
 
29
- /** The authenticated SDK clients (account / data / functions / meta). */
29
+ /** The authenticated SDK clients (account / agents / conversations / data / functions / knowledge / meta / storage). */
30
30
  export function useSdk(): ComponentSdk {
31
31
  return useRuntime().sdk
32
32
  }