{"version":3,"sources":["../../ui/src/applet-devtools/enabled.ts","../../ui/src/applet-core/context/AppletContext.tsx","../../ui/src/applet-core/hooks/useConfig.ts","../../ui/src/applet-core/hooks/useAppletRuntime.ts","../../ui/src/applet-devtools/overlay.tsx"],"names":["jsx"],"mappings":"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","file":"devtools.mjs","sourcesContent":["export function shouldEnableAppletDevtools(): boolean {\n  if (typeof window === 'undefined') {return false;}\n\n  const url = new URL(window.location.href);\n  if (url.searchParams.get('appletDebug') === '1') {return true;}\n\n  try {\n    return window.localStorage.getItem('iotaAppletDevtools') === '1';\n  } catch {\n    return false;\n  }\n}\n\n","import { createContext, useContext, ReactNode } from 'react';\nimport type { InitialContext } from '../types';\n\n/**\n * AppletContext provides access to the global context injected by the backend.\n * The context is read from window.__*_CONTEXT__ (configured via windowKey).\n */\nconst AppletContext = createContext<InitialContext | null>(null);\n\nconst REQUIRED_KEYS: Array<keyof InitialContext> = ['user', 'tenant', 'locale', 'config', 'route', 'session'];\n\nfunction validateInitialContext(value: unknown, windowKey: string): InitialContext {\n  if (!value || typeof value !== 'object') {\n    throw new Error(`${windowKey}: expected an object, got ${typeof value}`);\n  }\n  const obj = value as Record<string, unknown>;\n  const missing = REQUIRED_KEYS.filter((k) => !(k in obj));\n  if (missing.length > 0) {\n    throw new Error(`${windowKey}: missing required keys: ${missing.join(', ')}`);\n  }\n\n  // Deep validation for nested required fields\n  const user = obj.user as Record<string, unknown> | undefined;\n  if (!user || typeof user !== 'object') {\n    throw new Error(`${windowKey}.user: expected an object, got ${typeof user}`);\n  }\n  if (typeof user.id !== 'number') {\n    throw new Error(`${windowKey}.user.id: expected number, got ${typeof user.id}`);\n  }\n  if (!Array.isArray(user.permissions)) {\n    throw new Error(`${windowKey}.user.permissions: expected array, got ${typeof user.permissions}`);\n  }\n\n  const tenant = obj.tenant as Record<string, unknown> | undefined;\n  if (!tenant || typeof tenant !== 'object') {\n    throw new Error(`${windowKey}.tenant: expected an object, got ${typeof tenant}`);\n  }\n  if (typeof tenant.id !== 'string') {\n    throw new Error(`${windowKey}.tenant.id: expected string, got ${typeof tenant.id}`);\n  }\n\n  const session = obj.session as Record<string, unknown> | undefined;\n  if (!session || typeof session !== 'object') {\n    throw new Error(`${windowKey}.session: expected an object, got ${typeof session}`);\n  }\n  if (typeof session.csrfToken !== 'string') {\n    throw new Error(`${windowKey}.session.csrfToken: expected string, got ${typeof session.csrfToken}`);\n  }\n  if (typeof session.expiresAt !== 'number') {\n    throw new Error(`${windowKey}.session.expiresAt: expected number, got ${typeof session.expiresAt}`);\n  }\n  if (typeof session.refreshURL !== 'string') {\n    throw new Error(`${windowKey}.session.refreshURL: expected string, got ${typeof session.refreshURL}`);\n  }\n\n  const config = obj.config;\n  if (!config || typeof config !== 'object') {\n    throw new Error(`${windowKey}.config: expected object, got ${typeof config}`);\n  }\n\n  return value as InitialContext;\n}\n\nexport interface AppletProviderProps {\n  children: ReactNode\n  windowKey: string\n  context?: InitialContext\n}\n\n/**\n * AppletProvider reads context from window global and provides it to hooks.\n *\n * Usage:\n * <AppletProvider windowKey=\"__APPLET_CONTEXT__\">\n *   <App />\n * </AppletProvider>\n */\nexport function AppletProvider({ children, windowKey, context }: AppletProviderProps) {\n  // Use provided context or read from window global\n  const raw = context ?? (window as unknown as Record<string, unknown>)[windowKey];\n\n  if (!raw) {\n    throw new Error(`${windowKey} not found on window. Ensure backend context injection is working.`);\n  }\n\n  const initialContext = validateInitialContext(raw, windowKey);\n\n  return (\n    <AppletContext.Provider value={initialContext}>\n      {children}\n    </AppletContext.Provider>\n  );\n}\n\n/**\n * useAppletContext provides access to the full applet context.\n * Use specialized hooks (useUser, useConfig, etc.) for specific context parts.\n */\nexport function useAppletContext<T = InitialContext>(): T {\n  const context = useContext(AppletContext);\n  if (!context) {\n    throw new Error('useAppletContext must be used within AppletProvider');\n  }\n  return context as T;\n}\n","import { useAppletContext } from '../context/AppletContext';\nimport type { AppConfig } from '../types';\n\n/**\n * useConfig provides access to applet configuration (endpoints, etc.)\n *\n * Usage:\n * const { graphQLEndpoint, streamEndpoint } = useConfig()\n */\nexport function useConfig(): AppConfig {\n  const { config } = useAppletContext();\n  return config;\n}\n","import { useConfig } from './useConfig';\n\nexport type ShellMode = 'embedded' | 'standalone'\n\nexport interface AppletRuntime {\n  basePath: string\n  assetsBasePath: string\n  rpcEndpoint?: string\n  shellMode?: ShellMode\n}\n\nexport function useAppletRuntime(): AppletRuntime {\n  const config = useConfig();\n\n  const basePath = config.basePath ?? '';\n  const normalizedBasePath = basePath.endsWith('/') ? basePath.slice(0, -1) : basePath;\n  const assetsBasePath = config.assetsBasePath ?? `${normalizedBasePath || ''}/assets`;\n  const rpcEndpoint = config.rpcUIEndpoint;\n  const shellMode = config.shellMode;\n\n  return { basePath: normalizedBasePath, assetsBasePath, rpcEndpoint, shellMode };\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { useAppletContext } from '../applet-core/context/AppletContext';\nimport { useAppletRuntime } from '../applet-core/hooks/useAppletRuntime';\n\ntype RPCEvent = {\n  id: string\n  method: string\n  status: 'start' | 'success' | 'error'\n  durationMs?: number\n  error?: unknown\n}\n\nexport function AppletDevtoolsOverlay() {\n  const ctx = useAppletContext();\n  const runtime = useAppletRuntime();\n  const [rpcEvents, setRPCEvents] = useState<RPCEvent[]>([]);\n\n  useEffect(() => {\n    const onEvent = (e: Event) => {\n      if (!(e instanceof CustomEvent)) {return;}\n      const detail = (e as CustomEvent<RPCEvent>).detail;\n      if (!detail) {return;}\n      setRPCEvents((prev) => [detail, ...prev].slice(0, 50));\n    };\n    window.addEventListener('iota:applet-rpc', onEvent as EventListener);\n    return () => window.removeEventListener('iota:applet-rpc', onEvent as EventListener);\n  }, []);\n\n  const summary = useMemo(() => {\n    return {\n      basePath: runtime.basePath,\n      assetsBasePath: runtime.assetsBasePath,\n      rpcEndpoint: runtime.rpcEndpoint,\n      shellMode: runtime.shellMode,\n      route: ctx.route,\n      user: { id: ctx.user.id, email: ctx.user.email },\n      tenant: ctx.tenant,\n    };\n  }, [ctx.route, ctx.tenant, ctx.user.email, ctx.user.id, runtime.assetsBasePath, runtime.basePath, runtime.rpcEndpoint, runtime.shellMode]);\n\n  return (\n    <div\n      style={{\n        position: 'fixed',\n        right: 12,\n        bottom: 12,\n        width: 420,\n        maxHeight: '60vh',\n        overflow: 'auto',\n        background: 'rgba(17, 24, 39, 0.92)',\n        color: '#E5E7EB',\n        border: '1px solid rgba(255,255,255,0.12)',\n        borderRadius: 10,\n        padding: 12,\n        fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace',\n        fontSize: 12,\n        zIndex: 2147483647,\n      }}\n    >\n      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>\n        <div style={{ fontWeight: 700 }}>Applet Devtools</div>\n        <div style={{ opacity: 0.7 }}>{runtime.shellMode ?? 'unknown'}</div>\n      </div>\n\n      <div style={{ marginBottom: 10 }}>\n        <div style={{ opacity: 0.85, marginBottom: 4 }}>Context</div>\n        <pre style={{ margin: 0, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>{JSON.stringify(summary, null, 2)}</pre>\n      </div>\n\n      <div>\n        <div style={{ opacity: 0.85, marginBottom: 4 }}>RPC</div>\n        {rpcEvents.length === 0 ? (\n          <div style={{ opacity: 0.7 }}>No calls yet</div>\n        ) : (\n          <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n            {rpcEvents.map((ev) => (\n              <div key={`${ev.id}:${ev.status}`} style={{ padding: 8, border: '1px solid rgba(255,255,255,0.08)', borderRadius: 8 }}>\n                <div style={{ display: 'flex', justifyContent: 'space-between' }}>\n                  <div>{ev.method}</div>\n                  <div style={{ opacity: 0.8 }}>\n                    {ev.status}\n                    {typeof ev.durationMs === 'number' ? ` (${ev.durationMs}ms)` : ''}\n                  </div>\n                </div>\n                {ev.status === 'error' ? (\n                  <pre style={{ margin: '6px 0 0', opacity: 0.8, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>\n                    {JSON.stringify(serializeError(ev.error) ?? {}, null, 2)}\n                  </pre>\n                ) : null}\n              </div>\n            ))}\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n\nfunction serializeError(err: unknown): unknown {\n  if (err instanceof Error) {\n    const out: Record<string, unknown> = {\n      name: err.name,\n      message: err.message,\n    };\n    if (err.stack) {out.stack = err.stack;}\n    const errRecord = err as unknown as Record<string, unknown>;\n    if ('code' in err && typeof errRecord.code === 'string') {out.code = errRecord.code;}\n    if ('details' in err) {out.details = errRecord.details;}\n    if ('cause' in err) {out.cause = errRecord.cause;}\n    return out;\n  }\n  return err;\n}\n"]}