@weirdfingers/boards 0.3.0 → 0.4.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.
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/hooks/useBoards.ts +3 -1
package/dist/index.js
CHANGED
|
@@ -614,9 +614,10 @@ function useBoards(options = {}) {
|
|
|
614
614
|
if (!result.data?.createBoard) {
|
|
615
615
|
throw new Error("Failed to create board");
|
|
616
616
|
}
|
|
617
|
+
reexecuteQuery({ requestPolicy: "network-only" });
|
|
617
618
|
return result.data.createBoard;
|
|
618
619
|
},
|
|
619
|
-
[createBoardMutation]
|
|
620
|
+
[createBoardMutation, reexecuteQuery]
|
|
620
621
|
);
|
|
621
622
|
const deleteBoard = (0, import_react3.useCallback)(
|
|
622
623
|
async (boardId) => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/auth/context.tsx","../src/auth/providers/base.ts","../src/auth/providers/none.ts","../src/config/ApiConfigContext.tsx","../src/graphql/client.ts","../src/graphql/operations.ts","../src/hooks/useBoards.ts","../src/hooks/useBoard.ts","../src/hooks/useGeneration.ts","../src/hooks/useGenerators.ts","../src/utils/schemaParser.ts","../src/providers/BoardsProvider.tsx"],"sourcesContent":["export const VERSION = \"0.1.0\";\n\n// Core auth exports\nexport * from \"./auth/types\";\nexport * from \"./auth/hooks/useAuth\";\nexport { AuthProvider } from \"./auth/context\";\nexport { BaseAuthProvider } from \"./auth/providers/base\";\nexport { NoAuthProvider } from \"./auth/providers/none\"; // Only no-auth included for dev\n\n// API configuration\nexport { useApiConfig } from \"./config/ApiConfigContext\";\nexport type { ApiConfig } from \"./config/ApiConfigContext\";\n\n// GraphQL exports\nexport { createGraphQLClient } from \"./graphql/client\";\nexport * from \"./graphql/operations\";\n\n// Core hooks\nexport { useBoards } from \"./hooks/useBoards\";\nexport { useBoard } from \"./hooks/useBoard\";\nexport { useGeneration } from \"./hooks/useGeneration\";\nexport { useGenerators } from \"./hooks/useGenerators\";\nexport type { Generator, JSONSchema7 } from \"./hooks/useGenerators\";\n\n// Generator schema utilities\nexport * from \"./types/generatorSchema\";\nexport * from \"./utils/schemaParser\";\n\n// Provider components\nexport { BoardsProvider } from \"./providers/BoardsProvider\";\n","/**\n * React context for authentication.\n */\n\nimport React, { createContext, useContext, useEffect, useState, useCallback } from 'react';\nimport { AuthContextValue, AuthState } from './types';\nimport { BaseAuthProvider } from './providers/base';\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\ninterface AuthProviderProps {\n provider: BaseAuthProvider;\n children: React.ReactNode;\n}\n\nexport function AuthProvider({ provider, children }: AuthProviderProps) {\n const [state, setState] = useState<AuthState>({\n user: null,\n status: 'loading',\n signIn: async () => {},\n signOut: async () => {},\n getToken: async () => null,\n refreshToken: async () => null,\n });\n const [isInitializing, setIsInitializing] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const clearError = useCallback(() => {\n setError(null);\n }, []);\n\n useEffect(() => {\n let mounted = true;\n let unsubscribe: (() => void) | null = null;\n\n const initializeAuth = async () => {\n try {\n await provider.initialize();\n\n if (!mounted) return;\n\n // Set up state change listener\n unsubscribe = provider.onAuthStateChange((newState) => {\n if (mounted) {\n setState(newState);\n }\n });\n\n // Get initial state\n const initialState = await provider.getAuthState();\n if (mounted) {\n setState(initialState);\n setIsInitializing(false);\n }\n } catch (err) {\n if (mounted) {\n setError(err instanceof Error ? err : new Error('Auth initialization failed'));\n setIsInitializing(false);\n }\n }\n };\n\n initializeAuth();\n\n return () => {\n mounted = false;\n if (unsubscribe) {\n unsubscribe();\n }\n };\n }, [provider]);\n\n // Clean up provider on unmount\n useEffect(() => {\n return () => {\n provider.destroy();\n };\n }, [provider]);\n\n const contextValue: AuthContextValue = {\n ...state,\n isInitializing,\n error,\n clearError,\n };\n\n return (\n <AuthContext.Provider value={contextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n\nexport function useAuth(): AuthContextValue {\n const context = useContext(AuthContext);\n if (!context) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n return context;\n}\n\nexport function useAuthOptional(): AuthContextValue | null {\n return useContext(AuthContext);\n}\n","/**\n * Base authentication provider abstract class.\n */\n\nimport { AuthState, User, AuthProviderConfig } from '../types';\n\nexport abstract class BaseAuthProvider {\n protected config: AuthProviderConfig;\n\n constructor(config: AuthProviderConfig = {}) {\n this.config = config;\n }\n\n /**\n * Initialize the auth provider.\n * Called once when the provider is created.\n */\n abstract initialize(): Promise<void>;\n\n /**\n * Get the current authentication state.\n */\n abstract getAuthState(): Promise<AuthState>;\n\n /**\n * Sign in with the provider.\n */\n abstract signIn(opts?: Record<string, unknown>): Promise<void>;\n\n /**\n * Sign out from the provider.\n */\n abstract signOut(): Promise<void>;\n\n /**\n * Get the current authentication token.\n */\n abstract getToken(): Promise<string | null>;\n\n /**\n * Get the current user information.\n */\n abstract getUser(): Promise<User | null>;\n\n /**\n * Listen for auth state changes.\n * Returns an unsubscribe function.\n */\n abstract onAuthStateChange(callback: (state: AuthState) => void): () => void;\n\n /**\n * Clean up resources when the provider is destroyed.\n */\n abstract destroy(): Promise<void>;\n\n /**\n * Get the tenant ID from config.\n */\n protected getTenantId(): string {\n return this.config.tenantId || 'default';\n }\n}\n","/**\n * No-auth provider for local development without authentication.\n */\n\nimport { BaseAuthProvider } from \"./base\";\nimport { AuthState, User, AuthProviderConfig } from \"../types\";\n\ninterface NoAuthConfig extends AuthProviderConfig {\n /**\n * Default user ID for development.\n * Defaults to 'dev-user'.\n */\n defaultUserId?: string;\n\n /**\n * Default user email for development.\n * Defaults to 'dev@example.com'.\n */\n defaultEmail?: string;\n\n /**\n * Default display name for development.\n * Defaults to 'Development User'.\n */\n defaultDisplayName?: string;\n}\n\nexport class NoAuthProvider extends BaseAuthProvider {\n protected config: NoAuthConfig;\n private listeners: ((state: AuthState) => void)[] = [];\n private currentState: AuthState;\n private defaultUser: User;\n\n constructor(config: NoAuthConfig = {}) {\n super(config);\n\n // Production safety check\n const nodeEnv = typeof process !== \"undefined\" ? process.env?.NODE_ENV : \"\";\n const isDevelopment =\n nodeEnv === \"development\" || nodeEnv === \"\" || nodeEnv === \"test\";\n\n if (!isDevelopment) {\n const warning =\n \"NoAuthProvider is being used in a production environment. \" +\n \"This means authentication is disabled! \" +\n \"For production use on a server that is visible to the public, configure a proper authentication provider (JWT, Supabase, Clerk, etc.)\";\n console.warn(\"⚠️ SECURITY WARNING:\", warning);\n }\n\n this.config = {\n defaultUserId: \"dev-user\",\n defaultEmail: \"dev@example.com\",\n defaultDisplayName: \"Development User\",\n ...config,\n };\n\n this.defaultUser = {\n id: this.config.defaultUserId!,\n email: this.config.defaultEmail!,\n name: this.config.defaultDisplayName,\n avatar: undefined,\n metadata: { provider: \"none\" },\n credits: {\n balance: 1000,\n reserved: 0,\n },\n };\n\n this.currentState = {\n user: this.defaultUser,\n status: \"authenticated\", // Always authenticated in no-auth mode\n signIn: this.signIn.bind(this),\n signOut: this.signOut.bind(this),\n getToken: this.getToken.bind(this),\n refreshToken: this.refreshToken.bind(this),\n };\n\n // Use structured warning instead of console.warn\n if (console.warn) {\n console.warn(\n \"🚨 [AUTH] NoAuthProvider is active - authentication is disabled!\",\n {\n message: \"This should ONLY be used in development environments\",\n environment: nodeEnv || \"unknown\",\n provider: \"none\",\n }\n );\n }\n }\n\n async initialize(): Promise<void> {\n // No initialization needed - always authenticated\n this.updateState({ user: this.defaultUser, status: \"authenticated\" });\n }\n\n async getAuthState(): Promise<AuthState> {\n return this.currentState;\n }\n\n async signIn(): Promise<void> {\n // No-op in no-auth mode - already signed in\n if (console.info) {\n console.info(\"[AUTH] SignIn called in no-auth mode - no action taken\", {\n provider: \"none\",\n action: \"signIn\",\n status: \"ignored\",\n });\n }\n }\n\n async signOut(): Promise<void> {\n // No-op in no-auth mode - can't sign out\n if (console.info) {\n console.info(\"[AUTH] SignOut called in no-auth mode - no action taken\", {\n provider: \"none\",\n action: \"signOut\",\n status: \"ignored\",\n });\n }\n }\n\n async getToken(): Promise<string | null> {\n // Return a fake development token\n return \"dev-token|no-auth-mode|always-valid\";\n }\n\n async refreshToken(): Promise<string | null> {\n // Return the same fake token since it doesn't expire\n return \"dev-token|no-auth-mode|always-valid\";\n }\n\n async getUser(): Promise<User | null> {\n return this.defaultUser;\n }\n\n onAuthStateChange(callback: (state: AuthState) => void): () => void {\n // Call immediately with current state\n callback(this.currentState);\n\n this.listeners.push(callback);\n return () => {\n const index = this.listeners.indexOf(callback);\n if (index > -1) {\n this.listeners.splice(index, 1);\n }\n };\n }\n\n async destroy(): Promise<void> {\n this.listeners = [];\n }\n\n private updateState(updates: Partial<AuthState>): void {\n this.currentState = { ...this.currentState, ...updates };\n this.listeners.forEach((listener) => listener(this.currentState));\n }\n}\n","/**\n * API configuration context for providing backend URLs to hooks.\n */\n\nimport { createContext, useContext, ReactNode } from \"react\";\n\nexport interface ApiConfig {\n /**\n * Base URL for the backend API (e.g., \"http://localhost:8088\")\n * Used for REST endpoints like SSE streams\n */\n apiUrl: string;\n /**\n * GraphQL endpoint URL (e.g., \"http://localhost:8088/graphql\")\n */\n graphqlUrl: string;\n /**\n * WebSocket URL for GraphQL subscriptions\n */\n subscriptionUrl?: string;\n}\n\nconst ApiConfigContext = createContext<ApiConfig | null>(null);\n\ninterface ApiConfigProviderProps {\n children: ReactNode;\n config: ApiConfig;\n}\n\nexport function ApiConfigProvider({\n children,\n config,\n}: ApiConfigProviderProps) {\n return (\n <ApiConfigContext.Provider value={config}>\n {children}\n </ApiConfigContext.Provider>\n );\n}\n\nexport function useApiConfig(): ApiConfig {\n const context = useContext(ApiConfigContext);\n if (!context) {\n throw new Error(\"useApiConfig must be used within ApiConfigProvider\");\n }\n return context;\n}\n","/**\n * GraphQL client configuration with authentication.\n */\n\nimport {\n createClient,\n fetchExchange,\n cacheExchange,\n subscriptionExchange,\n makeOperation,\n} from \"urql\";\nimport { authExchange } from \"@urql/exchange-auth\";\nimport { createClient as createWSClient } from \"graphql-ws\";\n\ninterface AuthState {\n getToken(): Promise<string | null>;\n}\n\ninterface ClientConfig {\n url: string;\n subscriptionUrl?: string;\n auth: AuthState;\n tenantId?: string;\n}\n\nexport function createGraphQLClient({\n url,\n subscriptionUrl,\n auth,\n tenantId,\n}: ClientConfig) {\n const wsClient = subscriptionUrl\n ? createWSClient({\n url: subscriptionUrl,\n connectionParams: async () => {\n const token = await auth.getToken();\n const headers: Record<string, string> = {};\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n if (tenantId) {\n headers[\"X-Tenant\"] = tenantId;\n }\n\n return headers;\n },\n })\n : null;\n\n return createClient({\n url,\n exchanges: [\n cacheExchange,\n authExchange(async () => {\n // Initialize auth state by fetching token\n let token = await auth.getToken();\n\n return {\n addAuthToOperation: (operation) => {\n // Build headers\n const headers: Record<string, string> = {};\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n if (tenantId) {\n headers[\"X-Tenant\"] = tenantId;\n }\n const fetchOptions =\n typeof operation.context.fetchOptions === \"function\"\n ? operation.context.fetchOptions()\n : operation.context.fetchOptions || {};\n\n // Add headers to operation context\n return makeOperation(operation.kind, operation, {\n ...operation.context,\n fetchOptions: {\n ...operation.context.fetchOptions,\n headers: {\n ...fetchOptions.headers,\n ...headers,\n },\n },\n });\n },\n\n didAuthError: (error) => {\n // Check if error is auth-related\n return error.graphQLErrors.some(\n (e) =>\n e.extensions?.code === \"UNAUTHENTICATED\" ||\n e.extensions?.code === \"UNAUTHORIZED\"\n );\n },\n\n willAuthError: () => {\n // We don't preemptively block requests\n return false;\n },\n\n refreshAuth: async () => {\n // Re-fetch token on auth error and update the closure variable\n token = await auth.getToken();\n },\n };\n }),\n fetchExchange,\n ...(wsClient\n ? [\n subscriptionExchange({\n forwardSubscription: (operation) => ({\n subscribe: (sink) => ({\n unsubscribe: wsClient.subscribe(\n {\n query: operation.query || \"\",\n variables: operation.variables,\n },\n sink\n ),\n }),\n }),\n }),\n ]\n : []),\n ],\n });\n}\n","/**\n * GraphQL queries and mutations for the Boards API.\n */\n\nimport { gql } from \"urql\";\n\n// Fragments for reusable query parts\nexport const USER_FRAGMENT = gql`\n fragment UserFragment on User {\n id\n email\n displayName\n avatarUrl\n createdAt\n }\n`;\n\nexport const BOARD_FRAGMENT = gql`\n fragment BoardFragment on Board {\n id\n tenantId\n ownerId\n title\n description\n isPublic\n settings\n metadata\n createdAt\n updatedAt\n generationCount\n }\n`;\n\nexport const GENERATION_FRAGMENT = gql`\n fragment GenerationFragment on Generation {\n id\n boardId\n userId\n generatorName\n artifactType\n status\n progress\n storageUrl\n thumbnailUrl\n inputParams\n outputMetadata\n errorMessage\n createdAt\n updatedAt\n completedAt\n }\n`;\n\n// Auth queries\nexport const GET_CURRENT_USER = gql`\n ${USER_FRAGMENT}\n query GetCurrentUser {\n me {\n ...UserFragment\n }\n }\n`;\n\n// Board queries\nexport const GET_BOARDS = gql`\n ${BOARD_FRAGMENT}\n ${USER_FRAGMENT}\n query GetBoards($limit: Int, $offset: Int) {\n myBoards(limit: $limit, offset: $offset) {\n ...BoardFragment\n owner {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const GET_BOARD = gql`\n ${BOARD_FRAGMENT}\n ${USER_FRAGMENT}\n ${GENERATION_FRAGMENT}\n query GetBoard($id: UUID!) {\n board(id: $id) {\n ...BoardFragment\n owner {\n ...UserFragment\n }\n members {\n id\n boardId\n userId\n role\n invitedBy\n joinedAt\n user {\n ...UserFragment\n }\n inviter {\n ...UserFragment\n }\n }\n generations(limit: 10) {\n ...GenerationFragment\n }\n }\n }\n`;\n\n// Generator queries\nexport const GET_GENERATORS = gql`\n query GetGenerators($artifactType: String) {\n generators(artifactType: $artifactType) {\n name\n description\n artifactType\n inputSchema\n }\n }\n`;\n\n// Generation queries\nexport const GET_GENERATIONS = gql`\n ${GENERATION_FRAGMENT}\n query GetGenerations($boardId: UUID, $limit: Int, $offset: Int) {\n generations(boardId: $boardId, limit: $limit, offset: $offset) {\n ...GenerationFragment\n board {\n id\n title\n }\n user {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const GET_GENERATION = gql`\n ${GENERATION_FRAGMENT}\n query GetGeneration($id: UUID!) {\n generation(id: $id) {\n ...GenerationFragment\n board {\n ...BoardFragment\n }\n user {\n ...UserFragment\n }\n }\n }\n`;\n\n// Board mutations\nexport const CREATE_BOARD = gql`\n ${BOARD_FRAGMENT}\n ${USER_FRAGMENT}\n mutation CreateBoard($input: CreateBoardInput!) {\n createBoard(input: $input) {\n ...BoardFragment\n owner {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const UPDATE_BOARD = gql`\n ${BOARD_FRAGMENT}\n mutation UpdateBoard($id: UUID!, $input: UpdateBoardInput!) {\n updateBoard(id: $id, input: $input) {\n ...BoardFragment\n }\n }\n`;\n\nexport const DELETE_BOARD = gql`\n mutation DeleteBoard($id: UUID!) {\n deleteBoard(id: $id) {\n success\n }\n }\n`;\n\n// Board member mutations\nexport const ADD_BOARD_MEMBER = gql`\n mutation AddBoardMember($boardId: UUID!, $email: String!, $role: BoardRole!) {\n addBoardMember(boardId: $boardId, email: $email, role: $role) {\n id\n boardId\n userId\n role\n invitedBy\n joinedAt\n user {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const UPDATE_BOARD_MEMBER_ROLE = gql`\n mutation UpdateBoardMemberRole($id: UUID!, $role: BoardRole!) {\n updateBoardMemberRole(id: $id, role: $role) {\n id\n role\n }\n }\n`;\n\nexport const REMOVE_BOARD_MEMBER = gql`\n mutation RemoveBoardMember($id: UUID!) {\n removeBoardMember(id: $id) {\n success\n }\n }\n`;\n\n// Generation mutations\nexport const CREATE_GENERATION = gql`\n ${GENERATION_FRAGMENT}\n mutation CreateGeneration($input: CreateGenerationInput!) {\n createGeneration(input: $input) {\n ...GenerationFragment\n }\n }\n`;\n\nexport const CANCEL_GENERATION = gql`\n mutation CancelGeneration($id: UUID!) {\n cancelGeneration(id: $id) {\n id\n status\n }\n }\n`;\n\nexport const RETRY_GENERATION = gql`\n ${GENERATION_FRAGMENT}\n mutation RetryGeneration($id: UUID!) {\n retryGeneration(id: $id) {\n ...GenerationFragment\n }\n }\n`;\n\n// Input types (these should match your backend GraphQL schema)\nexport interface CreateBoardInput {\n title: string;\n description?: string;\n isPublic?: boolean;\n settings?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UpdateBoardInput {\n title?: string;\n description?: string;\n isPublic?: boolean;\n settings?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CreateGenerationInput {\n boardId: string;\n generatorName: string;\n artifactType: ArtifactType; // Allow string for flexibility with new types\n inputParams: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\n// Enums (should match backend)\nexport enum BoardRole {\n VIEWER = \"VIEWER\",\n EDITOR = \"EDITOR\",\n ADMIN = \"ADMIN\",\n}\n\nexport enum GenerationStatus {\n PENDING = \"PENDING\",\n RUNNING = \"RUNNING\",\n COMPLETED = \"COMPLETED\",\n FAILED = \"FAILED\",\n CANCELLED = \"CANCELLED\",\n}\n\nexport enum ArtifactType {\n IMAGE = \"image\",\n VIDEO = \"video\",\n AUDIO = \"audio\",\n TEXT = \"text\",\n LORA = \"lora\",\n MODEL = \"model\",\n}\n","/**\n * Hook for managing multiple boards.\n */\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport { useQuery, useMutation } from \"urql\";\n// import { Cache } from '@urql/core';\nimport {\n GET_BOARDS,\n CREATE_BOARD,\n DELETE_BOARD,\n CreateBoardInput,\n} from \"../graphql/operations\";\n\ninterface Board {\n id: string;\n tenantId: string;\n ownerId: string;\n title: string;\n description?: string;\n isPublic: boolean;\n settings: Record<string, unknown>;\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n generationCount: number;\n owner: {\n id: string;\n email: string;\n displayName: string;\n avatarUrl?: string;\n createdAt: string;\n };\n}\n\ninterface UseBoardsOptions {\n limit?: number;\n offset?: number;\n}\n\ninterface BoardsHook {\n boards: Board[];\n loading: boolean;\n error: Error | null;\n createBoard: (data: CreateBoardInput) => Promise<Board>;\n deleteBoard: (boardId: string) => Promise<void>;\n searchBoards: (query: string) => Promise<Board[]>;\n refresh: () => Promise<void>;\n setSearchQuery: (query: string) => void;\n searchQuery: string;\n}\n\nexport function useBoards(options: UseBoardsOptions = {}): BoardsHook {\n const { limit = 50, offset = 0 } = options;\n const [searchQuery, setSearchQuery] = useState(\"\");\n\n // Query for boards\n const [{ data, fetching, error }, reexecuteQuery] = useQuery({\n query: GET_BOARDS,\n variables: { limit, offset },\n });\n\n // Mutations\n const [, createBoardMutation] = useMutation(CREATE_BOARD);\n const [, deleteBoardMutation] = useMutation(DELETE_BOARD);\n\n const boards = useMemo(() => data?.myBoards || [], [data?.myBoards]);\n\n const createBoard = useCallback(\n async (input: CreateBoardInput): Promise<Board> => {\n const result = await createBoardMutation({ input });\n if (result.error) {\n throw new Error(result.error.message);\n }\n if (!result.data?.createBoard) {\n throw new Error(\"Failed to create board\");\n }\n return result.data.createBoard;\n },\n [createBoardMutation]\n );\n\n const deleteBoard = useCallback(\n async (boardId: string): Promise<void> => {\n const result = await deleteBoardMutation({ id: boardId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.deleteBoard?.success) {\n throw new Error(\"Failed to delete board\");\n }\n reexecuteQuery({ requestPolicy: \"network-only\" });\n },\n [deleteBoardMutation, reexecuteQuery]\n );\n\n const searchBoards = useCallback(\n async (query: string): Promise<Board[]> => {\n // Set search query which will trigger debounced search via useEffect\n setSearchQuery(query);\n\n // Return promise that resolves when search completes\n // This is a simplified implementation - in a real app you might want\n // to return the actual search results from the API\n return new Promise((resolve) => {\n // Wait for debounce delay plus a bit more for API response\n setTimeout(() => {\n resolve(\n boards.filter(\n (board: Board) =>\n board.title.toLowerCase().includes(query.toLowerCase()) ||\n board.description?.toLowerCase().includes(query.toLowerCase())\n )\n );\n }, 350);\n });\n },\n [boards]\n );\n\n const refresh = useCallback(async (): Promise<void> => {\n await reexecuteQuery({ requestPolicy: \"network-only\" });\n }, [reexecuteQuery]);\n\n return {\n boards,\n loading: fetching,\n error: error ? new Error(error.message) : null,\n createBoard,\n deleteBoard,\n searchBoards,\n refresh,\n setSearchQuery,\n searchQuery,\n };\n}\n","/**\n * Hook for managing a single board.\n */\n\nimport { useCallback, useMemo } from \"react\";\nimport { useQuery, useMutation } from \"urql\";\nimport { useAuth } from \"../auth/hooks/useAuth\";\nimport {\n GET_BOARD,\n UPDATE_BOARD,\n DELETE_BOARD,\n ADD_BOARD_MEMBER,\n UPDATE_BOARD_MEMBER_ROLE,\n REMOVE_BOARD_MEMBER,\n UpdateBoardInput,\n BoardRole,\n} from \"../graphql/operations\";\n\ninterface User {\n id: string;\n email: string;\n displayName: string;\n avatarUrl?: string;\n createdAt: string;\n}\n\ninterface BoardMember {\n id: string;\n boardId: string;\n userId: string;\n role: BoardRole;\n invitedBy?: string;\n joinedAt: string;\n user: User;\n inviter?: User;\n}\n\ninterface Generation {\n id: string;\n boardId: string;\n userId: string;\n generatorName: string;\n artifactType: string;\n status: string;\n progress: number;\n storageUrl?: string | null;\n thumbnailUrl?: string | null;\n inputParams: Record<string, unknown>;\n outputMetadata: Record<string, unknown>;\n errorMessage?: string | null;\n createdAt: string;\n updatedAt: string;\n completedAt?: string | null;\n}\n\ninterface Board {\n id: string;\n tenantId: string;\n ownerId: string;\n title: string;\n description?: string;\n isPublic: boolean;\n settings: Record<string, unknown>;\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n generationCount: number;\n owner: User;\n members: BoardMember[];\n generations: Generation[];\n}\n\ntype MemberRole = BoardRole;\n\ninterface BoardPermissions {\n canEdit: boolean;\n canDelete: boolean;\n canAddMembers: boolean;\n canRemoveMembers: boolean;\n canGenerate: boolean;\n canExport: boolean;\n}\n\ninterface ShareLinkOptions {\n expiresIn?: number;\n permissions?: string[];\n}\n\ninterface ShareLink {\n id: string;\n url: string;\n expiresAt?: string;\n permissions: string[];\n}\n\ninterface BoardHook {\n board: Board | null;\n members: BoardMember[];\n permissions: BoardPermissions;\n loading: boolean;\n error: Error | null;\n\n // Board operations\n updateBoard: (updates: Partial<UpdateBoardInput>) => Promise<Board>;\n deleteBoard: () => Promise<void>;\n refresh: () => Promise<void>;\n\n // Member management\n addMember: (email: string, role: MemberRole) => Promise<BoardMember>;\n removeMember: (memberId: string) => Promise<void>;\n updateMemberRole: (\n memberId: string,\n role: MemberRole\n ) => Promise<BoardMember>;\n\n // Sharing (placeholder - would need backend implementation)\n generateShareLink: (options: ShareLinkOptions) => Promise<ShareLink>;\n revokeShareLink: (linkId: string) => Promise<void>;\n}\n\nexport function useBoard(boardId: string): BoardHook {\n const { user } = useAuth();\n\n // Query for board data\n const [{ data, fetching, error }, reexecuteQuery] = useQuery({\n query: GET_BOARD,\n variables: { id: boardId },\n pause: !boardId,\n requestPolicy: \"cache-and-network\", // Always fetch fresh data while showing cached data\n });\n\n // Mutations\n const [, updateBoardMutation] = useMutation(UPDATE_BOARD);\n const [, deleteBoardMutation] = useMutation(DELETE_BOARD);\n const [, addMemberMutation] = useMutation(ADD_BOARD_MEMBER);\n const [, updateMemberRoleMutation] = useMutation(UPDATE_BOARD_MEMBER_ROLE);\n const [, removeMemberMutation] = useMutation(REMOVE_BOARD_MEMBER);\n\n const board = useMemo(() => data?.board || null, [data?.board]);\n const members = useMemo(() => board?.members || [], [board?.members]);\n\n // Calculate permissions based on user role\n const permissions = useMemo((): BoardPermissions => {\n if (!board || !user) {\n return {\n canEdit: false,\n canDelete: false,\n canAddMembers: false,\n canRemoveMembers: false,\n canGenerate: false,\n canExport: false,\n };\n }\n\n // Check if user is the board owner\n const isOwner = board.ownerId === user.id;\n\n // Find user's role in board members\n const userMember = members.find(\n (member: BoardMember) => member.userId === user.id\n );\n const userRole = userMember?.role;\n\n const isAdmin = userRole === BoardRole.ADMIN;\n const isEditor = userRole === BoardRole.EDITOR || isAdmin;\n const isViewer = userRole === BoardRole.VIEWER || isEditor;\n\n return {\n canEdit: isOwner || isAdmin || isEditor,\n canDelete: isOwner,\n canAddMembers: isOwner || isAdmin,\n canRemoveMembers: isOwner || isAdmin,\n canGenerate: isOwner || isAdmin || isEditor,\n canExport: isViewer, // Even viewers can export\n };\n }, [board, user, members]);\n\n const updateBoard = useCallback(\n async (updates: Partial<UpdateBoardInput>): Promise<Board> => {\n if (!boardId) {\n throw new Error(\"Board ID is required\");\n }\n\n const result = await updateBoardMutation({\n id: boardId,\n input: updates,\n });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.updateBoard) {\n throw new Error(\"Failed to update board\");\n }\n\n return result.data.updateBoard;\n },\n [boardId, updateBoardMutation]\n );\n\n const deleteBoard = useCallback(async (): Promise<void> => {\n if (!boardId) {\n throw new Error(\"Board ID is required\");\n }\n\n const result = await deleteBoardMutation({ id: boardId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.deleteBoard?.success) {\n throw new Error(\"Failed to delete board\");\n }\n }, [boardId, deleteBoardMutation]);\n\n const addMember = useCallback(\n async (email: string, role: MemberRole): Promise<BoardMember> => {\n if (!boardId) {\n throw new Error(\"Board ID is required\");\n }\n\n const result = await addMemberMutation({\n boardId,\n email,\n role,\n });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.addBoardMember) {\n throw new Error(\"Failed to add member\");\n }\n\n // Refresh board data to get updated members list\n reexecuteQuery({ requestPolicy: \"network-only\" });\n\n return result.data.addBoardMember;\n },\n [boardId, addMemberMutation, reexecuteQuery]\n );\n\n const removeMember = useCallback(\n async (memberId: string): Promise<void> => {\n const result = await removeMemberMutation({ id: memberId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.removeBoardMember?.success) {\n throw new Error(\"Failed to remove member\");\n }\n\n // Refresh board data to get updated members list\n reexecuteQuery({ requestPolicy: \"network-only\" });\n },\n [removeMemberMutation, reexecuteQuery]\n );\n\n const updateMemberRole = useCallback(\n async (memberId: string, role: MemberRole): Promise<BoardMember> => {\n const result = await updateMemberRoleMutation({\n id: memberId,\n role,\n });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.updateBoardMemberRole) {\n throw new Error(\"Failed to update member role\");\n }\n\n // Refresh board data to get updated members list\n reexecuteQuery({ requestPolicy: \"network-only\" });\n\n return result.data.updateBoardMemberRole;\n },\n [updateMemberRoleMutation, reexecuteQuery]\n );\n\n // Placeholder implementations for sharing features\n const generateShareLink = useCallback(\n async (_options: ShareLinkOptions): Promise<ShareLink> => {\n // TODO: Implement share link generation\n throw new Error(\"Share links not implemented yet\");\n },\n []\n );\n\n const revokeShareLink = useCallback(\n async (_linkId: string): Promise<void> => {\n // TODO: Implement share link revocation\n throw new Error(\"Share link revocation not implemented yet\");\n },\n []\n );\n\n const refresh = useCallback(async (): Promise<void> => {\n await reexecuteQuery({ requestPolicy: \"network-only\" });\n }, [reexecuteQuery]);\n\n return {\n board,\n members,\n permissions,\n loading: fetching,\n error: error ? new Error(error.message) : null,\n updateBoard,\n deleteBoard,\n refresh,\n addMember,\n removeMember,\n updateMemberRole,\n generateShareLink,\n revokeShareLink,\n };\n}\n","/**\n * Hook for managing AI generations with real-time progress via SSE.\n */\n\nimport { useCallback, useState, useEffect, useRef } from \"react\";\nimport { fetchEventSource } from \"@microsoft/fetch-event-source\";\nimport { useMutation } from \"urql\";\nimport {\n CREATE_GENERATION,\n CANCEL_GENERATION,\n RETRY_GENERATION,\n CreateGenerationInput,\n ArtifactType,\n} from \"../graphql/operations\";\nimport { useAuth } from \"../auth/context\";\nimport { useApiConfig } from \"../config/ApiConfigContext\";\n\nexport interface GenerationRequest {\n model: string;\n artifactType: ArtifactType; // Allow string for flexibility with new types\n inputs: GenerationInputs;\n boardId: string;\n options?: GenerationOptions;\n}\n\nexport interface GenerationInputs {\n prompt: string;\n negativePrompt?: string;\n image?: string | File;\n mask?: string | File;\n loras?: LoRAInput[];\n seed?: number;\n steps?: number;\n guidance?: number;\n aspectRatio?: string;\n style?: string;\n [key: string]: unknown;\n}\n\nexport interface GenerationOptions {\n priority?: \"low\" | \"normal\" | \"high\";\n timeout?: number;\n webhookUrl?: string;\n [key: string]: unknown;\n}\n\nexport interface LoRAInput {\n id: string;\n weight: number;\n}\n\nexport interface GenerationProgress {\n jobId: string;\n status: \"queued\" | \"processing\" | \"completed\" | \"failed\" | \"cancelled\";\n progress: number; // 0-100\n phase: string;\n message?: string | null;\n estimatedTimeRemaining?: number;\n currentStep?: string;\n logs?: string[];\n}\n\nexport interface GenerationResult {\n id: string;\n jobId: string;\n boardId: string;\n request: GenerationRequest;\n artifacts: Artifact[];\n credits: {\n cost: number;\n balanceBefore: number;\n balance: number;\n };\n performance: {\n queueTime: number;\n processingTime: number;\n totalTime: number;\n };\n createdAt: Date;\n}\n\nexport interface Artifact {\n id: string;\n type: string;\n url: string;\n thumbnailUrl?: string;\n metadata: Record<string, unknown>;\n}\n\nexport interface GenerationHook {\n // Current generation state\n progress: GenerationProgress | null;\n result: GenerationResult | null;\n error: Error | null;\n isGenerating: boolean;\n\n // Operations\n submit: (request: GenerationRequest) => Promise<string>;\n cancel: (jobId: string) => Promise<void>;\n retry: (jobId: string) => Promise<void>;\n\n // History\n history: GenerationResult[];\n clearHistory: () => void;\n}\n\nexport function useGeneration(): GenerationHook {\n const [progress, setProgress] = useState<GenerationProgress | null>(null);\n const [result, setResult] = useState<GenerationResult | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [isGenerating, setIsGenerating] = useState(false);\n const [history, setHistory] = useState<GenerationResult[]>([]);\n\n // Get API configuration and auth\n const { apiUrl } = useApiConfig();\n const auth = useAuth();\n\n // Keep track of active SSE connections (using AbortControllers)\n const abortControllers = useRef<Map<string, AbortController>>(new Map());\n\n // Mutations\n const [, createGenerationMutation] = useMutation(CREATE_GENERATION);\n const [, cancelGenerationMutation] = useMutation(CANCEL_GENERATION);\n const [, retryGenerationMutation] = useMutation(RETRY_GENERATION);\n\n // Clean up SSE connections on unmount\n useEffect(() => {\n return () => {\n abortControllers.current.forEach((controller) => {\n controller.abort();\n });\n abortControllers.current.clear();\n };\n }, []);\n\n const connectToSSE = useCallback(\n async (jobId: string) => {\n // Close existing connection if any\n const existingController = abortControllers.current.get(jobId);\n if (existingController) {\n existingController.abort();\n }\n\n // Create new abort controller\n const abortController = new AbortController();\n abortControllers.current.set(jobId, abortController);\n\n // Get auth token\n const token = await auth.getToken();\n\n // Build headers\n const headers: Record<string, string> = {\n Accept: \"text/event-stream\",\n };\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n // Connect to SSE endpoint directly\n const sseUrl = `${apiUrl}/api/sse/generations/${jobId}/progress`;\n console.log(\"SSE: Connecting to\", sseUrl, \"with headers:\", headers);\n\n try {\n await fetchEventSource(sseUrl, {\n headers,\n signal: abortController.signal,\n\n async onopen(response) {\n console.log(\n \"SSE: Connection opened\",\n response.status,\n response.statusText\n );\n if (response.ok) {\n console.log(\"SSE: Connection successful\");\n } else {\n console.error(\"SSE: Connection failed\", response.status);\n throw new Error(`SSE connection failed: ${response.statusText}`);\n }\n },\n\n onmessage(event) {\n console.log(\"SSE: Raw event received:\", event);\n\n // Skip empty messages (like keep-alive comments)\n if (!event.data || event.data.trim() === \"\") {\n console.log(\"SSE: Skipping empty message\");\n return;\n }\n\n try {\n const progressData: GenerationProgress = JSON.parse(event.data);\n console.log(\"SSE: progress data received:\", progressData);\n setProgress(progressData);\n\n // If generation is complete, handle the result\n if (\n progressData.status === \"completed\" ||\n progressData.status === \"failed\" ||\n progressData.status === \"cancelled\"\n ) {\n setIsGenerating(false);\n\n if (progressData.status === \"completed\") {\n // TODO: Fetch the complete result from GraphQL\n // For now, create a mock result\n const mockResult: GenerationResult = {\n id: progressData.jobId,\n jobId: progressData.jobId,\n boardId: \"\", // Would be filled from the original request\n request: {} as GenerationRequest,\n artifacts: [],\n credits: { cost: 0, balanceBefore: 0, balance: 0 },\n performance: {\n queueTime: 0,\n processingTime: 0,\n totalTime: 0,\n },\n createdAt: new Date(),\n };\n\n setResult(mockResult);\n setHistory((prev) => [...prev, mockResult]);\n } else if (progressData.status === \"failed\") {\n setError(new Error(\"Generation failed\"));\n }\n\n // Close connection\n abortController.abort();\n abortControllers.current.delete(jobId);\n }\n } catch (err) {\n console.error(\"Failed to parse SSE message:\", err);\n setError(new Error(\"Failed to parse progress update\"));\n setIsGenerating(false);\n abortController.abort();\n abortControllers.current.delete(jobId);\n }\n },\n\n onerror(err) {\n console.error(\"SSE connection error:\", err);\n console.error(\"SSE error details:\", {\n message: err instanceof Error ? err.message : String(err),\n jobId,\n url: sseUrl,\n });\n setError(new Error(\"Lost connection to generation progress\"));\n setIsGenerating(false);\n abortController.abort();\n abortControllers.current.delete(jobId);\n // Re-throw to stop retry\n throw err;\n },\n\n openWhenHidden: true, // Keep connection open when tab is hidden\n });\n } catch (err) {\n // Connection was aborted or failed\n if (abortController.signal.aborted) {\n console.log(\"SSE connection aborted for job:\", jobId);\n } else {\n console.error(\"SSE connection failed:\", err);\n }\n }\n },\n [apiUrl, auth]\n );\n\n const submit = useCallback(\n async (request: GenerationRequest): Promise<string> => {\n setError(null);\n setProgress(null);\n setResult(null);\n setIsGenerating(true);\n\n // Convert the request to the GraphQL input format\n const input: CreateGenerationInput = {\n boardId: request.boardId,\n generatorName: request.model,\n artifactType: request.artifactType,\n inputParams: {\n ...request.inputs,\n ...request.options,\n },\n };\n\n // Retry logic for generation submission\n let lastError: Error | null = null;\n const maxRetries = 2; // Fewer retries for generation as it's expensive\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n // Submit generation via GraphQL\n const result = await createGenerationMutation({ input });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.createGeneration) {\n throw new Error(\"Failed to create generation\");\n }\n\n const jobId = result.data.createGeneration.id;\n\n // Connect to SSE for progress updates\n connectToSSE(jobId);\n\n // Re-enable the submit button now that submission is complete\n // The SSE connection will continue tracking progress in the background\n setIsGenerating(false);\n\n return jobId;\n } catch (err) {\n lastError =\n err instanceof Error\n ? err\n : new Error(\"Failed to submit generation\");\n\n // Don't retry on certain types of errors\n if (\n lastError.message.includes(\"insufficient credits\") ||\n lastError.message.includes(\"validation\") ||\n lastError.message.includes(\"unauthorized\") ||\n lastError.message.includes(\"forbidden\")\n ) {\n setError(lastError);\n setIsGenerating(false);\n throw lastError;\n }\n\n // If this was the last attempt, throw the error\n if (attempt === maxRetries) {\n setError(lastError);\n setIsGenerating(false);\n throw lastError;\n }\n\n // Wait before retrying (shorter delay for generations)\n await new Promise((resolve) => setTimeout(resolve, 1000 * attempt));\n }\n }\n\n const finalError =\n lastError || new Error(\"Failed to submit generation after retries\");\n setError(finalError);\n setIsGenerating(false);\n throw finalError;\n },\n [createGenerationMutation, connectToSSE]\n );\n\n const cancel = useCallback(\n async (jobId: string): Promise<void> => {\n try {\n // Cancel via GraphQL\n const result = await cancelGenerationMutation({ id: jobId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n // Close SSE connection\n const controller = abortControllers.current.get(jobId);\n if (controller) {\n controller.abort();\n abortControllers.current.delete(jobId);\n }\n\n setIsGenerating(false);\n setProgress((prev) => (prev ? { ...prev, status: \"cancelled\" } : null));\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to cancel generation\")\n );\n }\n },\n [cancelGenerationMutation]\n );\n\n const retry = useCallback(\n async (jobId: string): Promise<void> => {\n try {\n setError(null);\n setIsGenerating(true);\n\n // Retry via GraphQL\n const result = await retryGenerationMutation({ id: jobId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.retryGeneration) {\n throw new Error(\"Failed to retry generation\");\n }\n\n const newJobId = result.data.retryGeneration.id;\n\n // Connect to SSE for the retried job\n connectToSSE(newJobId);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to retry generation\")\n );\n setIsGenerating(false);\n }\n },\n [retryGenerationMutation, connectToSSE]\n );\n\n const clearHistory = useCallback(() => {\n setHistory([]);\n }, []);\n\n return {\n progress,\n result,\n error,\n isGenerating,\n submit,\n cancel,\n retry,\n history,\n clearHistory,\n };\n}\n","/**\n * Hook for fetching available generators.\n */\n\nimport { useMemo } from \"react\";\nimport { useQuery } from \"urql\";\nimport type { JSONSchema7 } from \"json-schema\";\nimport { ArtifactType, GET_GENERATORS } from \"../graphql/operations\";\n\nexport interface Generator {\n name: string;\n description: string;\n artifactType: ArtifactType;\n inputSchema: JSONSchema7;\n}\n\n// Re-export JSONSchema7 for applications\nexport type { JSONSchema7 } from \"json-schema\";\n\ninterface UseGeneratorsOptions {\n artifactType?: string;\n}\n\ninterface GeneratorsHook {\n generators: Generator[];\n loading: boolean;\n error: Error | null;\n}\n\nexport function useGenerators(\n options: UseGeneratorsOptions = {}\n): GeneratorsHook {\n const { artifactType } = options;\n\n // Query for generators\n const [{ data, fetching, error }] = useQuery({\n query: GET_GENERATORS,\n variables: artifactType ? { artifactType } : {},\n });\n\n const generators = useMemo(() => data?.generators || [], [data?.generators]);\n\n return {\n generators,\n loading: fetching,\n error: error ? new Error(error.message) : null,\n };\n}\n","/**\n * Utilities for parsing generator JSON Schemas into structured data\n * suitable for dynamic UI generation.\n */\n\nimport type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport type {\n ParsedGeneratorSchema,\n ArtifactSlot,\n PromptField,\n SettingsField,\n} from \"../types/generatorSchema\";\n\n/**\n * Checks if a JSON Schema property references an artifact type.\n *\n * Artifacts are identified by $ref paths containing \"Artifact\" in their name,\n * e.g., \"#/$defs/AudioArtifact\" or \"#/$defs/VideoArtifact\".\n *\n * @param property - The JSON Schema property to check\n * @returns True if the property references an artifact type\n */\nexport function isArtifactReference(\n property: JSONSchema7 | JSONSchema7Definition | undefined\n): boolean {\n if (!property || typeof property === \"boolean\") {\n return false;\n }\n\n // Direct $ref to artifact\n if (property.$ref && property.$ref.includes(\"Artifact\")) {\n return true;\n }\n\n // Array with items that reference an artifact\n if (\n property.type === \"array\" &&\n property.items &&\n typeof property.items === \"object\" &&\n !Array.isArray(property.items)\n ) {\n const items = property.items as JSONSchema7;\n return !!(items.$ref && items.$ref.includes(\"Artifact\"));\n }\n\n return false;\n}\n\n/**\n * Extracts the artifact type from a $ref path.\n *\n * Examples:\n * - \"#/$defs/AudioArtifact\" -> \"audio\"\n * - \"#/$defs/VideoArtifact\" -> \"video\"\n * - \"#/$defs/ImageArtifact\" -> \"image\"\n * - \"#/$defs/TextArtifact\" -> \"text\"\n *\n * @param ref - The $ref string from the JSON Schema\n * @returns The artifact type in lowercase\n */\nexport function getArtifactType(\n ref: string\n): \"audio\" | \"video\" | \"image\" | \"text\" {\n const match = ref.match(/(Audio|Video|Image|Text)Artifact/);\n if (match) {\n return match[1].toLowerCase() as \"audio\" | \"video\" | \"image\" | \"text\";\n }\n\n // Fallback to \"image\" if pattern doesn't match\n return \"image\";\n}\n\n/**\n * Parses an artifact property into an ArtifactSlot structure.\n *\n * @param name - The property name from the schema\n * @param property - The JSON Schema property definition\n * @param required - Whether this field is in the required array\n * @returns Parsed artifact slot information\n */\nexport function parseArtifactSlot(\n name: string,\n property: JSONSchema7,\n required: boolean\n): ArtifactSlot {\n const title = property.title || name;\n const description = property.description;\n\n // Check if this is an array of artifacts\n if (property.type === \"array\" && property.items) {\n const items =\n typeof property.items === \"object\" && !Array.isArray(property.items)\n ? (property.items as JSONSchema7)\n : undefined;\n\n const artifactType = items?.$ref ? getArtifactType(items.$ref) : \"image\";\n\n return {\n name: title,\n fieldName: name,\n artifactType,\n required,\n description,\n isArray: true,\n minItems: property.minItems,\n maxItems: property.maxItems,\n };\n }\n\n // Single artifact\n const artifactType = property.$ref ? getArtifactType(property.$ref) : \"image\";\n\n return {\n name: title,\n fieldName: name,\n artifactType,\n required,\n description,\n isArray: false,\n };\n}\n\n/**\n * Determines if a numeric property should be rendered as a slider.\n *\n * A property is considered a slider if it's a number or integer type\n * and has both minimum and maximum values defined.\n *\n * @param property - The JSON Schema property to check\n * @returns True if this should be a slider\n */\nfunction isSlider(property: JSONSchema7): boolean {\n return (\n (property.type === \"number\" || property.type === \"integer\") &&\n property.minimum !== undefined &&\n property.maximum !== undefined\n );\n}\n\n/**\n * Parses a settings field into its appropriate type (slider, dropdown, text, number).\n *\n * @param name - The property name from the schema\n * @param property - The JSON Schema property definition\n * @returns Parsed settings field information\n */\nexport function parseSettingsField(\n name: string,\n property: JSONSchema7\n): SettingsField | null {\n const title = property.title || name;\n const description = property.description;\n\n // Dropdown (enum)\n if (property.enum && Array.isArray(property.enum)) {\n const options = property.enum.map((val) => String(val));\n const defaultValue =\n property.default !== undefined ? String(property.default) : undefined;\n\n return {\n type: \"dropdown\",\n fieldName: name,\n title,\n description,\n options,\n default: defaultValue,\n };\n }\n\n // Slider (number/integer with min/max)\n if (isSlider(property)) {\n const isInteger = property.type === \"integer\";\n return {\n type: \"slider\",\n fieldName: name,\n title,\n description,\n min: property.minimum as number,\n max: property.maximum as number,\n step: property.multipleOf,\n default:\n property.default !== undefined\n ? (property.default as number)\n : undefined,\n isInteger,\n };\n }\n\n // Number input (without slider constraints)\n if (property.type === \"number\" || property.type === \"integer\") {\n const isInteger = property.type === \"integer\";\n return {\n type: \"number\",\n fieldName: name,\n title,\n description,\n default:\n property.default !== undefined\n ? (property.default as number)\n : undefined,\n min: property.minimum as number | undefined,\n max: property.maximum as number | undefined,\n isInteger,\n };\n }\n\n // Text input\n if (property.type === \"string\") {\n return {\n type: \"text\",\n fieldName: name,\n title,\n description,\n default:\n property.default !== undefined ? String(property.default) : undefined,\n pattern: property.pattern,\n };\n }\n\n // Unsupported type\n return null;\n}\n\n/**\n * Parses a complete generator JSON Schema into structured data for UI generation.\n *\n * This function categorizes schema properties into:\n * - Artifact slots (for selecting existing artifacts)\n * - Prompt field (special text input for generation prompts)\n * - Settings fields (sliders, dropdowns, text inputs, etc.)\n *\n * @param schema - The JSON Schema from the generator's inputSchema field\n * @returns Parsed schema structure ready for dynamic UI generation\n *\n * @example\n * ```typescript\n * const generator = generators[0];\n * const parsed = parseGeneratorSchema(generator.inputSchema);\n *\n * // Render artifact slots\n * parsed.artifactSlots.forEach(slot => {\n * console.log(`${slot.name}: ${slot.artifactType} (required: ${slot.required})`);\n * });\n *\n * // Render prompt field\n * if (parsed.promptField) {\n * console.log(`Prompt: ${parsed.promptField.description}`);\n * }\n *\n * // Render settings\n * parsed.settingsFields.forEach(field => {\n * if (field.type === 'slider') {\n * console.log(`${field.title}: ${field.min} - ${field.max}`);\n * }\n * });\n * ```\n */\nexport function parseGeneratorSchema(\n schema: JSONSchema7\n): ParsedGeneratorSchema {\n const artifactSlots: ArtifactSlot[] = [];\n const settingsFields: SettingsField[] = [];\n let promptField: PromptField | null = null;\n\n if (!schema.properties) {\n return { artifactSlots, promptField, settingsFields };\n }\n\n const required = schema.required || [];\n\n for (const [name, propertyDef] of Object.entries(schema.properties)) {\n if (typeof propertyDef === \"boolean\") {\n continue;\n }\n\n const property = propertyDef as JSONSchema7;\n const isRequired = required.includes(name);\n\n // Check if this is an artifact reference\n if (isArtifactReference(property)) {\n const slot = parseArtifactSlot(name, property, isRequired);\n artifactSlots.push(slot);\n continue;\n }\n\n // Check if this is the prompt field\n if (name === \"prompt\" && property.type === \"string\") {\n promptField = {\n fieldName: name,\n description: property.description,\n required: isRequired,\n default:\n property.default !== undefined ? String(property.default) : undefined,\n };\n continue;\n }\n\n // Everything else goes to settings\n const settingsField = parseSettingsField(name, property);\n if (settingsField) {\n settingsFields.push(settingsField);\n }\n }\n\n return {\n artifactSlots,\n promptField,\n settingsFields,\n };\n}\n","/**\n * Main provider component that sets up GraphQL client and auth context.\n */\n\nimport { ReactNode } from \"react\";\nimport { Provider as UrqlProvider } from \"urql\";\nimport { createGraphQLClient } from \"../graphql/client\";\nimport { AuthProvider } from \"../auth/context\";\nimport { BaseAuthProvider } from \"../auth/providers/base\";\nimport { ApiConfigProvider, ApiConfig } from \"../config/ApiConfigContext\";\n\ninterface BoardsProviderProps {\n children: ReactNode;\n /**\n * Base URL for the backend API (e.g., \"http://localhost:8088\")\n * Used for REST endpoints like SSE streams\n */\n apiUrl: string;\n /**\n * GraphQL endpoint URL (e.g., \"http://localhost:8088/graphql\")\n * If not provided, defaults to `${apiUrl}/graphql`\n */\n graphqlUrl?: string;\n /**\n * WebSocket URL for GraphQL subscriptions\n */\n subscriptionUrl?: string;\n authProvider: BaseAuthProvider;\n tenantId?: string;\n}\n\nexport function BoardsProvider({\n children,\n apiUrl,\n graphqlUrl,\n subscriptionUrl,\n authProvider,\n tenantId,\n}: BoardsProviderProps) {\n // Default graphqlUrl if not provided\n const resolvedGraphqlUrl = graphqlUrl || `${apiUrl}/graphql`;\n\n // Create API config for hooks\n const apiConfig: ApiConfig = {\n apiUrl,\n graphqlUrl: resolvedGraphqlUrl,\n subscriptionUrl,\n };\n\n // Create the GraphQL client with auth integration\n const client = createGraphQLClient({\n url: resolvedGraphqlUrl,\n subscriptionUrl,\n auth: {\n getToken: () =>\n authProvider.getAuthState().then((state) => state.getToken()),\n },\n tenantId,\n });\n\n return (\n <AuthProvider provider={authProvider}>\n <ApiConfigProvider config={apiConfig}>\n <UrqlProvider value={client}>{children}</UrqlProvider>\n </ApiConfigProvider>\n </AuthProvider>\n );\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","createWSClient","import_urql","BoardRole","GenerationStatus","ArtifactType","import_react","import_urql","import_react","import_urql","import_react","import_urql","result","import_react","import_urql","artifactType","import_urql","import_jsx_runtime","UrqlProvider"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/auth/context.tsx","../src/auth/providers/base.ts","../src/auth/providers/none.ts","../src/config/ApiConfigContext.tsx","../src/graphql/client.ts","../src/graphql/operations.ts","../src/hooks/useBoards.ts","../src/hooks/useBoard.ts","../src/hooks/useGeneration.ts","../src/hooks/useGenerators.ts","../src/utils/schemaParser.ts","../src/providers/BoardsProvider.tsx"],"sourcesContent":["export const VERSION = \"0.1.0\";\n\n// Core auth exports\nexport * from \"./auth/types\";\nexport * from \"./auth/hooks/useAuth\";\nexport { AuthProvider } from \"./auth/context\";\nexport { BaseAuthProvider } from \"./auth/providers/base\";\nexport { NoAuthProvider } from \"./auth/providers/none\"; // Only no-auth included for dev\n\n// API configuration\nexport { useApiConfig } from \"./config/ApiConfigContext\";\nexport type { ApiConfig } from \"./config/ApiConfigContext\";\n\n// GraphQL exports\nexport { createGraphQLClient } from \"./graphql/client\";\nexport * from \"./graphql/operations\";\n\n// Core hooks\nexport { useBoards } from \"./hooks/useBoards\";\nexport { useBoard } from \"./hooks/useBoard\";\nexport { useGeneration } from \"./hooks/useGeneration\";\nexport { useGenerators } from \"./hooks/useGenerators\";\nexport type { Generator, JSONSchema7 } from \"./hooks/useGenerators\";\n\n// Generator schema utilities\nexport * from \"./types/generatorSchema\";\nexport * from \"./utils/schemaParser\";\n\n// Provider components\nexport { BoardsProvider } from \"./providers/BoardsProvider\";\n","/**\n * React context for authentication.\n */\n\nimport React, { createContext, useContext, useEffect, useState, useCallback } from 'react';\nimport { AuthContextValue, AuthState } from './types';\nimport { BaseAuthProvider } from './providers/base';\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\ninterface AuthProviderProps {\n provider: BaseAuthProvider;\n children: React.ReactNode;\n}\n\nexport function AuthProvider({ provider, children }: AuthProviderProps) {\n const [state, setState] = useState<AuthState>({\n user: null,\n status: 'loading',\n signIn: async () => {},\n signOut: async () => {},\n getToken: async () => null,\n refreshToken: async () => null,\n });\n const [isInitializing, setIsInitializing] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const clearError = useCallback(() => {\n setError(null);\n }, []);\n\n useEffect(() => {\n let mounted = true;\n let unsubscribe: (() => void) | null = null;\n\n const initializeAuth = async () => {\n try {\n await provider.initialize();\n\n if (!mounted) return;\n\n // Set up state change listener\n unsubscribe = provider.onAuthStateChange((newState) => {\n if (mounted) {\n setState(newState);\n }\n });\n\n // Get initial state\n const initialState = await provider.getAuthState();\n if (mounted) {\n setState(initialState);\n setIsInitializing(false);\n }\n } catch (err) {\n if (mounted) {\n setError(err instanceof Error ? err : new Error('Auth initialization failed'));\n setIsInitializing(false);\n }\n }\n };\n\n initializeAuth();\n\n return () => {\n mounted = false;\n if (unsubscribe) {\n unsubscribe();\n }\n };\n }, [provider]);\n\n // Clean up provider on unmount\n useEffect(() => {\n return () => {\n provider.destroy();\n };\n }, [provider]);\n\n const contextValue: AuthContextValue = {\n ...state,\n isInitializing,\n error,\n clearError,\n };\n\n return (\n <AuthContext.Provider value={contextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n\nexport function useAuth(): AuthContextValue {\n const context = useContext(AuthContext);\n if (!context) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n return context;\n}\n\nexport function useAuthOptional(): AuthContextValue | null {\n return useContext(AuthContext);\n}\n","/**\n * Base authentication provider abstract class.\n */\n\nimport { AuthState, User, AuthProviderConfig } from '../types';\n\nexport abstract class BaseAuthProvider {\n protected config: AuthProviderConfig;\n\n constructor(config: AuthProviderConfig = {}) {\n this.config = config;\n }\n\n /**\n * Initialize the auth provider.\n * Called once when the provider is created.\n */\n abstract initialize(): Promise<void>;\n\n /**\n * Get the current authentication state.\n */\n abstract getAuthState(): Promise<AuthState>;\n\n /**\n * Sign in with the provider.\n */\n abstract signIn(opts?: Record<string, unknown>): Promise<void>;\n\n /**\n * Sign out from the provider.\n */\n abstract signOut(): Promise<void>;\n\n /**\n * Get the current authentication token.\n */\n abstract getToken(): Promise<string | null>;\n\n /**\n * Get the current user information.\n */\n abstract getUser(): Promise<User | null>;\n\n /**\n * Listen for auth state changes.\n * Returns an unsubscribe function.\n */\n abstract onAuthStateChange(callback: (state: AuthState) => void): () => void;\n\n /**\n * Clean up resources when the provider is destroyed.\n */\n abstract destroy(): Promise<void>;\n\n /**\n * Get the tenant ID from config.\n */\n protected getTenantId(): string {\n return this.config.tenantId || 'default';\n }\n}\n","/**\n * No-auth provider for local development without authentication.\n */\n\nimport { BaseAuthProvider } from \"./base\";\nimport { AuthState, User, AuthProviderConfig } from \"../types\";\n\ninterface NoAuthConfig extends AuthProviderConfig {\n /**\n * Default user ID for development.\n * Defaults to 'dev-user'.\n */\n defaultUserId?: string;\n\n /**\n * Default user email for development.\n * Defaults to 'dev@example.com'.\n */\n defaultEmail?: string;\n\n /**\n * Default display name for development.\n * Defaults to 'Development User'.\n */\n defaultDisplayName?: string;\n}\n\nexport class NoAuthProvider extends BaseAuthProvider {\n protected config: NoAuthConfig;\n private listeners: ((state: AuthState) => void)[] = [];\n private currentState: AuthState;\n private defaultUser: User;\n\n constructor(config: NoAuthConfig = {}) {\n super(config);\n\n // Production safety check\n const nodeEnv = typeof process !== \"undefined\" ? process.env?.NODE_ENV : \"\";\n const isDevelopment =\n nodeEnv === \"development\" || nodeEnv === \"\" || nodeEnv === \"test\";\n\n if (!isDevelopment) {\n const warning =\n \"NoAuthProvider is being used in a production environment. \" +\n \"This means authentication is disabled! \" +\n \"For production use on a server that is visible to the public, configure a proper authentication provider (JWT, Supabase, Clerk, etc.)\";\n console.warn(\"⚠️ SECURITY WARNING:\", warning);\n }\n\n this.config = {\n defaultUserId: \"dev-user\",\n defaultEmail: \"dev@example.com\",\n defaultDisplayName: \"Development User\",\n ...config,\n };\n\n this.defaultUser = {\n id: this.config.defaultUserId!,\n email: this.config.defaultEmail!,\n name: this.config.defaultDisplayName,\n avatar: undefined,\n metadata: { provider: \"none\" },\n credits: {\n balance: 1000,\n reserved: 0,\n },\n };\n\n this.currentState = {\n user: this.defaultUser,\n status: \"authenticated\", // Always authenticated in no-auth mode\n signIn: this.signIn.bind(this),\n signOut: this.signOut.bind(this),\n getToken: this.getToken.bind(this),\n refreshToken: this.refreshToken.bind(this),\n };\n\n // Use structured warning instead of console.warn\n if (console.warn) {\n console.warn(\n \"🚨 [AUTH] NoAuthProvider is active - authentication is disabled!\",\n {\n message: \"This should ONLY be used in development environments\",\n environment: nodeEnv || \"unknown\",\n provider: \"none\",\n }\n );\n }\n }\n\n async initialize(): Promise<void> {\n // No initialization needed - always authenticated\n this.updateState({ user: this.defaultUser, status: \"authenticated\" });\n }\n\n async getAuthState(): Promise<AuthState> {\n return this.currentState;\n }\n\n async signIn(): Promise<void> {\n // No-op in no-auth mode - already signed in\n if (console.info) {\n console.info(\"[AUTH] SignIn called in no-auth mode - no action taken\", {\n provider: \"none\",\n action: \"signIn\",\n status: \"ignored\",\n });\n }\n }\n\n async signOut(): Promise<void> {\n // No-op in no-auth mode - can't sign out\n if (console.info) {\n console.info(\"[AUTH] SignOut called in no-auth mode - no action taken\", {\n provider: \"none\",\n action: \"signOut\",\n status: \"ignored\",\n });\n }\n }\n\n async getToken(): Promise<string | null> {\n // Return a fake development token\n return \"dev-token|no-auth-mode|always-valid\";\n }\n\n async refreshToken(): Promise<string | null> {\n // Return the same fake token since it doesn't expire\n return \"dev-token|no-auth-mode|always-valid\";\n }\n\n async getUser(): Promise<User | null> {\n return this.defaultUser;\n }\n\n onAuthStateChange(callback: (state: AuthState) => void): () => void {\n // Call immediately with current state\n callback(this.currentState);\n\n this.listeners.push(callback);\n return () => {\n const index = this.listeners.indexOf(callback);\n if (index > -1) {\n this.listeners.splice(index, 1);\n }\n };\n }\n\n async destroy(): Promise<void> {\n this.listeners = [];\n }\n\n private updateState(updates: Partial<AuthState>): void {\n this.currentState = { ...this.currentState, ...updates };\n this.listeners.forEach((listener) => listener(this.currentState));\n }\n}\n","/**\n * API configuration context for providing backend URLs to hooks.\n */\n\nimport { createContext, useContext, ReactNode } from \"react\";\n\nexport interface ApiConfig {\n /**\n * Base URL for the backend API (e.g., \"http://localhost:8088\")\n * Used for REST endpoints like SSE streams\n */\n apiUrl: string;\n /**\n * GraphQL endpoint URL (e.g., \"http://localhost:8088/graphql\")\n */\n graphqlUrl: string;\n /**\n * WebSocket URL for GraphQL subscriptions\n */\n subscriptionUrl?: string;\n}\n\nconst ApiConfigContext = createContext<ApiConfig | null>(null);\n\ninterface ApiConfigProviderProps {\n children: ReactNode;\n config: ApiConfig;\n}\n\nexport function ApiConfigProvider({\n children,\n config,\n}: ApiConfigProviderProps) {\n return (\n <ApiConfigContext.Provider value={config}>\n {children}\n </ApiConfigContext.Provider>\n );\n}\n\nexport function useApiConfig(): ApiConfig {\n const context = useContext(ApiConfigContext);\n if (!context) {\n throw new Error(\"useApiConfig must be used within ApiConfigProvider\");\n }\n return context;\n}\n","/**\n * GraphQL client configuration with authentication.\n */\n\nimport {\n createClient,\n fetchExchange,\n cacheExchange,\n subscriptionExchange,\n makeOperation,\n} from \"urql\";\nimport { authExchange } from \"@urql/exchange-auth\";\nimport { createClient as createWSClient } from \"graphql-ws\";\n\ninterface AuthState {\n getToken(): Promise<string | null>;\n}\n\ninterface ClientConfig {\n url: string;\n subscriptionUrl?: string;\n auth: AuthState;\n tenantId?: string;\n}\n\nexport function createGraphQLClient({\n url,\n subscriptionUrl,\n auth,\n tenantId,\n}: ClientConfig) {\n const wsClient = subscriptionUrl\n ? createWSClient({\n url: subscriptionUrl,\n connectionParams: async () => {\n const token = await auth.getToken();\n const headers: Record<string, string> = {};\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n if (tenantId) {\n headers[\"X-Tenant\"] = tenantId;\n }\n\n return headers;\n },\n })\n : null;\n\n return createClient({\n url,\n exchanges: [\n cacheExchange,\n authExchange(async () => {\n // Initialize auth state by fetching token\n let token = await auth.getToken();\n\n return {\n addAuthToOperation: (operation) => {\n // Build headers\n const headers: Record<string, string> = {};\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n if (tenantId) {\n headers[\"X-Tenant\"] = tenantId;\n }\n const fetchOptions =\n typeof operation.context.fetchOptions === \"function\"\n ? operation.context.fetchOptions()\n : operation.context.fetchOptions || {};\n\n // Add headers to operation context\n return makeOperation(operation.kind, operation, {\n ...operation.context,\n fetchOptions: {\n ...operation.context.fetchOptions,\n headers: {\n ...fetchOptions.headers,\n ...headers,\n },\n },\n });\n },\n\n didAuthError: (error) => {\n // Check if error is auth-related\n return error.graphQLErrors.some(\n (e) =>\n e.extensions?.code === \"UNAUTHENTICATED\" ||\n e.extensions?.code === \"UNAUTHORIZED\"\n );\n },\n\n willAuthError: () => {\n // We don't preemptively block requests\n return false;\n },\n\n refreshAuth: async () => {\n // Re-fetch token on auth error and update the closure variable\n token = await auth.getToken();\n },\n };\n }),\n fetchExchange,\n ...(wsClient\n ? [\n subscriptionExchange({\n forwardSubscription: (operation) => ({\n subscribe: (sink) => ({\n unsubscribe: wsClient.subscribe(\n {\n query: operation.query || \"\",\n variables: operation.variables,\n },\n sink\n ),\n }),\n }),\n }),\n ]\n : []),\n ],\n });\n}\n","/**\n * GraphQL queries and mutations for the Boards API.\n */\n\nimport { gql } from \"urql\";\n\n// Fragments for reusable query parts\nexport const USER_FRAGMENT = gql`\n fragment UserFragment on User {\n id\n email\n displayName\n avatarUrl\n createdAt\n }\n`;\n\nexport const BOARD_FRAGMENT = gql`\n fragment BoardFragment on Board {\n id\n tenantId\n ownerId\n title\n description\n isPublic\n settings\n metadata\n createdAt\n updatedAt\n generationCount\n }\n`;\n\nexport const GENERATION_FRAGMENT = gql`\n fragment GenerationFragment on Generation {\n id\n boardId\n userId\n generatorName\n artifactType\n status\n progress\n storageUrl\n thumbnailUrl\n inputParams\n outputMetadata\n errorMessage\n createdAt\n updatedAt\n completedAt\n }\n`;\n\n// Auth queries\nexport const GET_CURRENT_USER = gql`\n ${USER_FRAGMENT}\n query GetCurrentUser {\n me {\n ...UserFragment\n }\n }\n`;\n\n// Board queries\nexport const GET_BOARDS = gql`\n ${BOARD_FRAGMENT}\n ${USER_FRAGMENT}\n query GetBoards($limit: Int, $offset: Int) {\n myBoards(limit: $limit, offset: $offset) {\n ...BoardFragment\n owner {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const GET_BOARD = gql`\n ${BOARD_FRAGMENT}\n ${USER_FRAGMENT}\n ${GENERATION_FRAGMENT}\n query GetBoard($id: UUID!) {\n board(id: $id) {\n ...BoardFragment\n owner {\n ...UserFragment\n }\n members {\n id\n boardId\n userId\n role\n invitedBy\n joinedAt\n user {\n ...UserFragment\n }\n inviter {\n ...UserFragment\n }\n }\n generations(limit: 10) {\n ...GenerationFragment\n }\n }\n }\n`;\n\n// Generator queries\nexport const GET_GENERATORS = gql`\n query GetGenerators($artifactType: String) {\n generators(artifactType: $artifactType) {\n name\n description\n artifactType\n inputSchema\n }\n }\n`;\n\n// Generation queries\nexport const GET_GENERATIONS = gql`\n ${GENERATION_FRAGMENT}\n query GetGenerations($boardId: UUID, $limit: Int, $offset: Int) {\n generations(boardId: $boardId, limit: $limit, offset: $offset) {\n ...GenerationFragment\n board {\n id\n title\n }\n user {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const GET_GENERATION = gql`\n ${GENERATION_FRAGMENT}\n query GetGeneration($id: UUID!) {\n generation(id: $id) {\n ...GenerationFragment\n board {\n ...BoardFragment\n }\n user {\n ...UserFragment\n }\n }\n }\n`;\n\n// Board mutations\nexport const CREATE_BOARD = gql`\n ${BOARD_FRAGMENT}\n ${USER_FRAGMENT}\n mutation CreateBoard($input: CreateBoardInput!) {\n createBoard(input: $input) {\n ...BoardFragment\n owner {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const UPDATE_BOARD = gql`\n ${BOARD_FRAGMENT}\n mutation UpdateBoard($id: UUID!, $input: UpdateBoardInput!) {\n updateBoard(id: $id, input: $input) {\n ...BoardFragment\n }\n }\n`;\n\nexport const DELETE_BOARD = gql`\n mutation DeleteBoard($id: UUID!) {\n deleteBoard(id: $id) {\n success\n }\n }\n`;\n\n// Board member mutations\nexport const ADD_BOARD_MEMBER = gql`\n mutation AddBoardMember($boardId: UUID!, $email: String!, $role: BoardRole!) {\n addBoardMember(boardId: $boardId, email: $email, role: $role) {\n id\n boardId\n userId\n role\n invitedBy\n joinedAt\n user {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const UPDATE_BOARD_MEMBER_ROLE = gql`\n mutation UpdateBoardMemberRole($id: UUID!, $role: BoardRole!) {\n updateBoardMemberRole(id: $id, role: $role) {\n id\n role\n }\n }\n`;\n\nexport const REMOVE_BOARD_MEMBER = gql`\n mutation RemoveBoardMember($id: UUID!) {\n removeBoardMember(id: $id) {\n success\n }\n }\n`;\n\n// Generation mutations\nexport const CREATE_GENERATION = gql`\n ${GENERATION_FRAGMENT}\n mutation CreateGeneration($input: CreateGenerationInput!) {\n createGeneration(input: $input) {\n ...GenerationFragment\n }\n }\n`;\n\nexport const CANCEL_GENERATION = gql`\n mutation CancelGeneration($id: UUID!) {\n cancelGeneration(id: $id) {\n id\n status\n }\n }\n`;\n\nexport const RETRY_GENERATION = gql`\n ${GENERATION_FRAGMENT}\n mutation RetryGeneration($id: UUID!) {\n retryGeneration(id: $id) {\n ...GenerationFragment\n }\n }\n`;\n\n// Input types (these should match your backend GraphQL schema)\nexport interface CreateBoardInput {\n title: string;\n description?: string;\n isPublic?: boolean;\n settings?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UpdateBoardInput {\n title?: string;\n description?: string;\n isPublic?: boolean;\n settings?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CreateGenerationInput {\n boardId: string;\n generatorName: string;\n artifactType: ArtifactType; // Allow string for flexibility with new types\n inputParams: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\n// Enums (should match backend)\nexport enum BoardRole {\n VIEWER = \"VIEWER\",\n EDITOR = \"EDITOR\",\n ADMIN = \"ADMIN\",\n}\n\nexport enum GenerationStatus {\n PENDING = \"PENDING\",\n RUNNING = \"RUNNING\",\n COMPLETED = \"COMPLETED\",\n FAILED = \"FAILED\",\n CANCELLED = \"CANCELLED\",\n}\n\nexport enum ArtifactType {\n IMAGE = \"image\",\n VIDEO = \"video\",\n AUDIO = \"audio\",\n TEXT = \"text\",\n LORA = \"lora\",\n MODEL = \"model\",\n}\n","/**\n * Hook for managing multiple boards.\n */\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport { useQuery, useMutation } from \"urql\";\n// import { Cache } from '@urql/core';\nimport {\n GET_BOARDS,\n CREATE_BOARD,\n DELETE_BOARD,\n CreateBoardInput,\n} from \"../graphql/operations\";\n\ninterface Board {\n id: string;\n tenantId: string;\n ownerId: string;\n title: string;\n description?: string;\n isPublic: boolean;\n settings: Record<string, unknown>;\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n generationCount: number;\n owner: {\n id: string;\n email: string;\n displayName: string;\n avatarUrl?: string;\n createdAt: string;\n };\n}\n\ninterface UseBoardsOptions {\n limit?: number;\n offset?: number;\n}\n\ninterface BoardsHook {\n boards: Board[];\n loading: boolean;\n error: Error | null;\n createBoard: (data: CreateBoardInput) => Promise<Board>;\n deleteBoard: (boardId: string) => Promise<void>;\n searchBoards: (query: string) => Promise<Board[]>;\n refresh: () => Promise<void>;\n setSearchQuery: (query: string) => void;\n searchQuery: string;\n}\n\nexport function useBoards(options: UseBoardsOptions = {}): BoardsHook {\n const { limit = 50, offset = 0 } = options;\n const [searchQuery, setSearchQuery] = useState(\"\");\n\n // Query for boards\n const [{ data, fetching, error }, reexecuteQuery] = useQuery({\n query: GET_BOARDS,\n variables: { limit, offset },\n });\n\n // Mutations\n const [, createBoardMutation] = useMutation(CREATE_BOARD);\n const [, deleteBoardMutation] = useMutation(DELETE_BOARD);\n\n const boards = useMemo(() => data?.myBoards || [], [data?.myBoards]);\n\n const createBoard = useCallback(\n async (input: CreateBoardInput): Promise<Board> => {\n const result = await createBoardMutation({ input });\n if (result.error) {\n throw new Error(result.error.message);\n }\n if (!result.data?.createBoard) {\n throw new Error(\"Failed to create board\");\n }\n // Refetch boards to update the UI with the new board\n reexecuteQuery({ requestPolicy: \"network-only\" });\n return result.data.createBoard;\n },\n [createBoardMutation, reexecuteQuery]\n );\n\n const deleteBoard = useCallback(\n async (boardId: string): Promise<void> => {\n const result = await deleteBoardMutation({ id: boardId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.deleteBoard?.success) {\n throw new Error(\"Failed to delete board\");\n }\n reexecuteQuery({ requestPolicy: \"network-only\" });\n },\n [deleteBoardMutation, reexecuteQuery]\n );\n\n const searchBoards = useCallback(\n async (query: string): Promise<Board[]> => {\n // Set search query which will trigger debounced search via useEffect\n setSearchQuery(query);\n\n // Return promise that resolves when search completes\n // This is a simplified implementation - in a real app you might want\n // to return the actual search results from the API\n return new Promise((resolve) => {\n // Wait for debounce delay plus a bit more for API response\n setTimeout(() => {\n resolve(\n boards.filter(\n (board: Board) =>\n board.title.toLowerCase().includes(query.toLowerCase()) ||\n board.description?.toLowerCase().includes(query.toLowerCase())\n )\n );\n }, 350);\n });\n },\n [boards]\n );\n\n const refresh = useCallback(async (): Promise<void> => {\n await reexecuteQuery({ requestPolicy: \"network-only\" });\n }, [reexecuteQuery]);\n\n return {\n boards,\n loading: fetching,\n error: error ? new Error(error.message) : null,\n createBoard,\n deleteBoard,\n searchBoards,\n refresh,\n setSearchQuery,\n searchQuery,\n };\n}\n","/**\n * Hook for managing a single board.\n */\n\nimport { useCallback, useMemo } from \"react\";\nimport { useQuery, useMutation } from \"urql\";\nimport { useAuth } from \"../auth/hooks/useAuth\";\nimport {\n GET_BOARD,\n UPDATE_BOARD,\n DELETE_BOARD,\n ADD_BOARD_MEMBER,\n UPDATE_BOARD_MEMBER_ROLE,\n REMOVE_BOARD_MEMBER,\n UpdateBoardInput,\n BoardRole,\n} from \"../graphql/operations\";\n\ninterface User {\n id: string;\n email: string;\n displayName: string;\n avatarUrl?: string;\n createdAt: string;\n}\n\ninterface BoardMember {\n id: string;\n boardId: string;\n userId: string;\n role: BoardRole;\n invitedBy?: string;\n joinedAt: string;\n user: User;\n inviter?: User;\n}\n\ninterface Generation {\n id: string;\n boardId: string;\n userId: string;\n generatorName: string;\n artifactType: string;\n status: string;\n progress: number;\n storageUrl?: string | null;\n thumbnailUrl?: string | null;\n inputParams: Record<string, unknown>;\n outputMetadata: Record<string, unknown>;\n errorMessage?: string | null;\n createdAt: string;\n updatedAt: string;\n completedAt?: string | null;\n}\n\ninterface Board {\n id: string;\n tenantId: string;\n ownerId: string;\n title: string;\n description?: string;\n isPublic: boolean;\n settings: Record<string, unknown>;\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n generationCount: number;\n owner: User;\n members: BoardMember[];\n generations: Generation[];\n}\n\ntype MemberRole = BoardRole;\n\ninterface BoardPermissions {\n canEdit: boolean;\n canDelete: boolean;\n canAddMembers: boolean;\n canRemoveMembers: boolean;\n canGenerate: boolean;\n canExport: boolean;\n}\n\ninterface ShareLinkOptions {\n expiresIn?: number;\n permissions?: string[];\n}\n\ninterface ShareLink {\n id: string;\n url: string;\n expiresAt?: string;\n permissions: string[];\n}\n\ninterface BoardHook {\n board: Board | null;\n members: BoardMember[];\n permissions: BoardPermissions;\n loading: boolean;\n error: Error | null;\n\n // Board operations\n updateBoard: (updates: Partial<UpdateBoardInput>) => Promise<Board>;\n deleteBoard: () => Promise<void>;\n refresh: () => Promise<void>;\n\n // Member management\n addMember: (email: string, role: MemberRole) => Promise<BoardMember>;\n removeMember: (memberId: string) => Promise<void>;\n updateMemberRole: (\n memberId: string,\n role: MemberRole\n ) => Promise<BoardMember>;\n\n // Sharing (placeholder - would need backend implementation)\n generateShareLink: (options: ShareLinkOptions) => Promise<ShareLink>;\n revokeShareLink: (linkId: string) => Promise<void>;\n}\n\nexport function useBoard(boardId: string): BoardHook {\n const { user } = useAuth();\n\n // Query for board data\n const [{ data, fetching, error }, reexecuteQuery] = useQuery({\n query: GET_BOARD,\n variables: { id: boardId },\n pause: !boardId,\n requestPolicy: \"cache-and-network\", // Always fetch fresh data while showing cached data\n });\n\n // Mutations\n const [, updateBoardMutation] = useMutation(UPDATE_BOARD);\n const [, deleteBoardMutation] = useMutation(DELETE_BOARD);\n const [, addMemberMutation] = useMutation(ADD_BOARD_MEMBER);\n const [, updateMemberRoleMutation] = useMutation(UPDATE_BOARD_MEMBER_ROLE);\n const [, removeMemberMutation] = useMutation(REMOVE_BOARD_MEMBER);\n\n const board = useMemo(() => data?.board || null, [data?.board]);\n const members = useMemo(() => board?.members || [], [board?.members]);\n\n // Calculate permissions based on user role\n const permissions = useMemo((): BoardPermissions => {\n if (!board || !user) {\n return {\n canEdit: false,\n canDelete: false,\n canAddMembers: false,\n canRemoveMembers: false,\n canGenerate: false,\n canExport: false,\n };\n }\n\n // Check if user is the board owner\n const isOwner = board.ownerId === user.id;\n\n // Find user's role in board members\n const userMember = members.find(\n (member: BoardMember) => member.userId === user.id\n );\n const userRole = userMember?.role;\n\n const isAdmin = userRole === BoardRole.ADMIN;\n const isEditor = userRole === BoardRole.EDITOR || isAdmin;\n const isViewer = userRole === BoardRole.VIEWER || isEditor;\n\n return {\n canEdit: isOwner || isAdmin || isEditor,\n canDelete: isOwner,\n canAddMembers: isOwner || isAdmin,\n canRemoveMembers: isOwner || isAdmin,\n canGenerate: isOwner || isAdmin || isEditor,\n canExport: isViewer, // Even viewers can export\n };\n }, [board, user, members]);\n\n const updateBoard = useCallback(\n async (updates: Partial<UpdateBoardInput>): Promise<Board> => {\n if (!boardId) {\n throw new Error(\"Board ID is required\");\n }\n\n const result = await updateBoardMutation({\n id: boardId,\n input: updates,\n });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.updateBoard) {\n throw new Error(\"Failed to update board\");\n }\n\n return result.data.updateBoard;\n },\n [boardId, updateBoardMutation]\n );\n\n const deleteBoard = useCallback(async (): Promise<void> => {\n if (!boardId) {\n throw new Error(\"Board ID is required\");\n }\n\n const result = await deleteBoardMutation({ id: boardId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.deleteBoard?.success) {\n throw new Error(\"Failed to delete board\");\n }\n }, [boardId, deleteBoardMutation]);\n\n const addMember = useCallback(\n async (email: string, role: MemberRole): Promise<BoardMember> => {\n if (!boardId) {\n throw new Error(\"Board ID is required\");\n }\n\n const result = await addMemberMutation({\n boardId,\n email,\n role,\n });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.addBoardMember) {\n throw new Error(\"Failed to add member\");\n }\n\n // Refresh board data to get updated members list\n reexecuteQuery({ requestPolicy: \"network-only\" });\n\n return result.data.addBoardMember;\n },\n [boardId, addMemberMutation, reexecuteQuery]\n );\n\n const removeMember = useCallback(\n async (memberId: string): Promise<void> => {\n const result = await removeMemberMutation({ id: memberId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.removeBoardMember?.success) {\n throw new Error(\"Failed to remove member\");\n }\n\n // Refresh board data to get updated members list\n reexecuteQuery({ requestPolicy: \"network-only\" });\n },\n [removeMemberMutation, reexecuteQuery]\n );\n\n const updateMemberRole = useCallback(\n async (memberId: string, role: MemberRole): Promise<BoardMember> => {\n const result = await updateMemberRoleMutation({\n id: memberId,\n role,\n });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.updateBoardMemberRole) {\n throw new Error(\"Failed to update member role\");\n }\n\n // Refresh board data to get updated members list\n reexecuteQuery({ requestPolicy: \"network-only\" });\n\n return result.data.updateBoardMemberRole;\n },\n [updateMemberRoleMutation, reexecuteQuery]\n );\n\n // Placeholder implementations for sharing features\n const generateShareLink = useCallback(\n async (_options: ShareLinkOptions): Promise<ShareLink> => {\n // TODO: Implement share link generation\n throw new Error(\"Share links not implemented yet\");\n },\n []\n );\n\n const revokeShareLink = useCallback(\n async (_linkId: string): Promise<void> => {\n // TODO: Implement share link revocation\n throw new Error(\"Share link revocation not implemented yet\");\n },\n []\n );\n\n const refresh = useCallback(async (): Promise<void> => {\n await reexecuteQuery({ requestPolicy: \"network-only\" });\n }, [reexecuteQuery]);\n\n return {\n board,\n members,\n permissions,\n loading: fetching,\n error: error ? new Error(error.message) : null,\n updateBoard,\n deleteBoard,\n refresh,\n addMember,\n removeMember,\n updateMemberRole,\n generateShareLink,\n revokeShareLink,\n };\n}\n","/**\n * Hook for managing AI generations with real-time progress via SSE.\n */\n\nimport { useCallback, useState, useEffect, useRef } from \"react\";\nimport { fetchEventSource } from \"@microsoft/fetch-event-source\";\nimport { useMutation } from \"urql\";\nimport {\n CREATE_GENERATION,\n CANCEL_GENERATION,\n RETRY_GENERATION,\n CreateGenerationInput,\n ArtifactType,\n} from \"../graphql/operations\";\nimport { useAuth } from \"../auth/context\";\nimport { useApiConfig } from \"../config/ApiConfigContext\";\n\nexport interface GenerationRequest {\n model: string;\n artifactType: ArtifactType; // Allow string for flexibility with new types\n inputs: GenerationInputs;\n boardId: string;\n options?: GenerationOptions;\n}\n\nexport interface GenerationInputs {\n prompt: string;\n negativePrompt?: string;\n image?: string | File;\n mask?: string | File;\n loras?: LoRAInput[];\n seed?: number;\n steps?: number;\n guidance?: number;\n aspectRatio?: string;\n style?: string;\n [key: string]: unknown;\n}\n\nexport interface GenerationOptions {\n priority?: \"low\" | \"normal\" | \"high\";\n timeout?: number;\n webhookUrl?: string;\n [key: string]: unknown;\n}\n\nexport interface LoRAInput {\n id: string;\n weight: number;\n}\n\nexport interface GenerationProgress {\n jobId: string;\n status: \"queued\" | \"processing\" | \"completed\" | \"failed\" | \"cancelled\";\n progress: number; // 0-100\n phase: string;\n message?: string | null;\n estimatedTimeRemaining?: number;\n currentStep?: string;\n logs?: string[];\n}\n\nexport interface GenerationResult {\n id: string;\n jobId: string;\n boardId: string;\n request: GenerationRequest;\n artifacts: Artifact[];\n credits: {\n cost: number;\n balanceBefore: number;\n balance: number;\n };\n performance: {\n queueTime: number;\n processingTime: number;\n totalTime: number;\n };\n createdAt: Date;\n}\n\nexport interface Artifact {\n id: string;\n type: string;\n url: string;\n thumbnailUrl?: string;\n metadata: Record<string, unknown>;\n}\n\nexport interface GenerationHook {\n // Current generation state\n progress: GenerationProgress | null;\n result: GenerationResult | null;\n error: Error | null;\n isGenerating: boolean;\n\n // Operations\n submit: (request: GenerationRequest) => Promise<string>;\n cancel: (jobId: string) => Promise<void>;\n retry: (jobId: string) => Promise<void>;\n\n // History\n history: GenerationResult[];\n clearHistory: () => void;\n}\n\nexport function useGeneration(): GenerationHook {\n const [progress, setProgress] = useState<GenerationProgress | null>(null);\n const [result, setResult] = useState<GenerationResult | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [isGenerating, setIsGenerating] = useState(false);\n const [history, setHistory] = useState<GenerationResult[]>([]);\n\n // Get API configuration and auth\n const { apiUrl } = useApiConfig();\n const auth = useAuth();\n\n // Keep track of active SSE connections (using AbortControllers)\n const abortControllers = useRef<Map<string, AbortController>>(new Map());\n\n // Mutations\n const [, createGenerationMutation] = useMutation(CREATE_GENERATION);\n const [, cancelGenerationMutation] = useMutation(CANCEL_GENERATION);\n const [, retryGenerationMutation] = useMutation(RETRY_GENERATION);\n\n // Clean up SSE connections on unmount\n useEffect(() => {\n return () => {\n abortControllers.current.forEach((controller) => {\n controller.abort();\n });\n abortControllers.current.clear();\n };\n }, []);\n\n const connectToSSE = useCallback(\n async (jobId: string) => {\n // Close existing connection if any\n const existingController = abortControllers.current.get(jobId);\n if (existingController) {\n existingController.abort();\n }\n\n // Create new abort controller\n const abortController = new AbortController();\n abortControllers.current.set(jobId, abortController);\n\n // Get auth token\n const token = await auth.getToken();\n\n // Build headers\n const headers: Record<string, string> = {\n Accept: \"text/event-stream\",\n };\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n // Connect to SSE endpoint directly\n const sseUrl = `${apiUrl}/api/sse/generations/${jobId}/progress`;\n console.log(\"SSE: Connecting to\", sseUrl, \"with headers:\", headers);\n\n try {\n await fetchEventSource(sseUrl, {\n headers,\n signal: abortController.signal,\n\n async onopen(response) {\n console.log(\n \"SSE: Connection opened\",\n response.status,\n response.statusText\n );\n if (response.ok) {\n console.log(\"SSE: Connection successful\");\n } else {\n console.error(\"SSE: Connection failed\", response.status);\n throw new Error(`SSE connection failed: ${response.statusText}`);\n }\n },\n\n onmessage(event) {\n console.log(\"SSE: Raw event received:\", event);\n\n // Skip empty messages (like keep-alive comments)\n if (!event.data || event.data.trim() === \"\") {\n console.log(\"SSE: Skipping empty message\");\n return;\n }\n\n try {\n const progressData: GenerationProgress = JSON.parse(event.data);\n console.log(\"SSE: progress data received:\", progressData);\n setProgress(progressData);\n\n // If generation is complete, handle the result\n if (\n progressData.status === \"completed\" ||\n progressData.status === \"failed\" ||\n progressData.status === \"cancelled\"\n ) {\n setIsGenerating(false);\n\n if (progressData.status === \"completed\") {\n // TODO: Fetch the complete result from GraphQL\n // For now, create a mock result\n const mockResult: GenerationResult = {\n id: progressData.jobId,\n jobId: progressData.jobId,\n boardId: \"\", // Would be filled from the original request\n request: {} as GenerationRequest,\n artifacts: [],\n credits: { cost: 0, balanceBefore: 0, balance: 0 },\n performance: {\n queueTime: 0,\n processingTime: 0,\n totalTime: 0,\n },\n createdAt: new Date(),\n };\n\n setResult(mockResult);\n setHistory((prev) => [...prev, mockResult]);\n } else if (progressData.status === \"failed\") {\n setError(new Error(\"Generation failed\"));\n }\n\n // Close connection\n abortController.abort();\n abortControllers.current.delete(jobId);\n }\n } catch (err) {\n console.error(\"Failed to parse SSE message:\", err);\n setError(new Error(\"Failed to parse progress update\"));\n setIsGenerating(false);\n abortController.abort();\n abortControllers.current.delete(jobId);\n }\n },\n\n onerror(err) {\n console.error(\"SSE connection error:\", err);\n console.error(\"SSE error details:\", {\n message: err instanceof Error ? err.message : String(err),\n jobId,\n url: sseUrl,\n });\n setError(new Error(\"Lost connection to generation progress\"));\n setIsGenerating(false);\n abortController.abort();\n abortControllers.current.delete(jobId);\n // Re-throw to stop retry\n throw err;\n },\n\n openWhenHidden: true, // Keep connection open when tab is hidden\n });\n } catch (err) {\n // Connection was aborted or failed\n if (abortController.signal.aborted) {\n console.log(\"SSE connection aborted for job:\", jobId);\n } else {\n console.error(\"SSE connection failed:\", err);\n }\n }\n },\n [apiUrl, auth]\n );\n\n const submit = useCallback(\n async (request: GenerationRequest): Promise<string> => {\n setError(null);\n setProgress(null);\n setResult(null);\n setIsGenerating(true);\n\n // Convert the request to the GraphQL input format\n const input: CreateGenerationInput = {\n boardId: request.boardId,\n generatorName: request.model,\n artifactType: request.artifactType,\n inputParams: {\n ...request.inputs,\n ...request.options,\n },\n };\n\n // Retry logic for generation submission\n let lastError: Error | null = null;\n const maxRetries = 2; // Fewer retries for generation as it's expensive\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n // Submit generation via GraphQL\n const result = await createGenerationMutation({ input });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.createGeneration) {\n throw new Error(\"Failed to create generation\");\n }\n\n const jobId = result.data.createGeneration.id;\n\n // Connect to SSE for progress updates\n connectToSSE(jobId);\n\n // Re-enable the submit button now that submission is complete\n // The SSE connection will continue tracking progress in the background\n setIsGenerating(false);\n\n return jobId;\n } catch (err) {\n lastError =\n err instanceof Error\n ? err\n : new Error(\"Failed to submit generation\");\n\n // Don't retry on certain types of errors\n if (\n lastError.message.includes(\"insufficient credits\") ||\n lastError.message.includes(\"validation\") ||\n lastError.message.includes(\"unauthorized\") ||\n lastError.message.includes(\"forbidden\")\n ) {\n setError(lastError);\n setIsGenerating(false);\n throw lastError;\n }\n\n // If this was the last attempt, throw the error\n if (attempt === maxRetries) {\n setError(lastError);\n setIsGenerating(false);\n throw lastError;\n }\n\n // Wait before retrying (shorter delay for generations)\n await new Promise((resolve) => setTimeout(resolve, 1000 * attempt));\n }\n }\n\n const finalError =\n lastError || new Error(\"Failed to submit generation after retries\");\n setError(finalError);\n setIsGenerating(false);\n throw finalError;\n },\n [createGenerationMutation, connectToSSE]\n );\n\n const cancel = useCallback(\n async (jobId: string): Promise<void> => {\n try {\n // Cancel via GraphQL\n const result = await cancelGenerationMutation({ id: jobId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n // Close SSE connection\n const controller = abortControllers.current.get(jobId);\n if (controller) {\n controller.abort();\n abortControllers.current.delete(jobId);\n }\n\n setIsGenerating(false);\n setProgress((prev) => (prev ? { ...prev, status: \"cancelled\" } : null));\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to cancel generation\")\n );\n }\n },\n [cancelGenerationMutation]\n );\n\n const retry = useCallback(\n async (jobId: string): Promise<void> => {\n try {\n setError(null);\n setIsGenerating(true);\n\n // Retry via GraphQL\n const result = await retryGenerationMutation({ id: jobId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.retryGeneration) {\n throw new Error(\"Failed to retry generation\");\n }\n\n const newJobId = result.data.retryGeneration.id;\n\n // Connect to SSE for the retried job\n connectToSSE(newJobId);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to retry generation\")\n );\n setIsGenerating(false);\n }\n },\n [retryGenerationMutation, connectToSSE]\n );\n\n const clearHistory = useCallback(() => {\n setHistory([]);\n }, []);\n\n return {\n progress,\n result,\n error,\n isGenerating,\n submit,\n cancel,\n retry,\n history,\n clearHistory,\n };\n}\n","/**\n * Hook for fetching available generators.\n */\n\nimport { useMemo } from \"react\";\nimport { useQuery } from \"urql\";\nimport type { JSONSchema7 } from \"json-schema\";\nimport { ArtifactType, GET_GENERATORS } from \"../graphql/operations\";\n\nexport interface Generator {\n name: string;\n description: string;\n artifactType: ArtifactType;\n inputSchema: JSONSchema7;\n}\n\n// Re-export JSONSchema7 for applications\nexport type { JSONSchema7 } from \"json-schema\";\n\ninterface UseGeneratorsOptions {\n artifactType?: string;\n}\n\ninterface GeneratorsHook {\n generators: Generator[];\n loading: boolean;\n error: Error | null;\n}\n\nexport function useGenerators(\n options: UseGeneratorsOptions = {}\n): GeneratorsHook {\n const { artifactType } = options;\n\n // Query for generators\n const [{ data, fetching, error }] = useQuery({\n query: GET_GENERATORS,\n variables: artifactType ? { artifactType } : {},\n });\n\n const generators = useMemo(() => data?.generators || [], [data?.generators]);\n\n return {\n generators,\n loading: fetching,\n error: error ? new Error(error.message) : null,\n };\n}\n","/**\n * Utilities for parsing generator JSON Schemas into structured data\n * suitable for dynamic UI generation.\n */\n\nimport type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport type {\n ParsedGeneratorSchema,\n ArtifactSlot,\n PromptField,\n SettingsField,\n} from \"../types/generatorSchema\";\n\n/**\n * Checks if a JSON Schema property references an artifact type.\n *\n * Artifacts are identified by $ref paths containing \"Artifact\" in their name,\n * e.g., \"#/$defs/AudioArtifact\" or \"#/$defs/VideoArtifact\".\n *\n * @param property - The JSON Schema property to check\n * @returns True if the property references an artifact type\n */\nexport function isArtifactReference(\n property: JSONSchema7 | JSONSchema7Definition | undefined\n): boolean {\n if (!property || typeof property === \"boolean\") {\n return false;\n }\n\n // Direct $ref to artifact\n if (property.$ref && property.$ref.includes(\"Artifact\")) {\n return true;\n }\n\n // Array with items that reference an artifact\n if (\n property.type === \"array\" &&\n property.items &&\n typeof property.items === \"object\" &&\n !Array.isArray(property.items)\n ) {\n const items = property.items as JSONSchema7;\n return !!(items.$ref && items.$ref.includes(\"Artifact\"));\n }\n\n return false;\n}\n\n/**\n * Extracts the artifact type from a $ref path.\n *\n * Examples:\n * - \"#/$defs/AudioArtifact\" -> \"audio\"\n * - \"#/$defs/VideoArtifact\" -> \"video\"\n * - \"#/$defs/ImageArtifact\" -> \"image\"\n * - \"#/$defs/TextArtifact\" -> \"text\"\n *\n * @param ref - The $ref string from the JSON Schema\n * @returns The artifact type in lowercase\n */\nexport function getArtifactType(\n ref: string\n): \"audio\" | \"video\" | \"image\" | \"text\" {\n const match = ref.match(/(Audio|Video|Image|Text)Artifact/);\n if (match) {\n return match[1].toLowerCase() as \"audio\" | \"video\" | \"image\" | \"text\";\n }\n\n // Fallback to \"image\" if pattern doesn't match\n return \"image\";\n}\n\n/**\n * Parses an artifact property into an ArtifactSlot structure.\n *\n * @param name - The property name from the schema\n * @param property - The JSON Schema property definition\n * @param required - Whether this field is in the required array\n * @returns Parsed artifact slot information\n */\nexport function parseArtifactSlot(\n name: string,\n property: JSONSchema7,\n required: boolean\n): ArtifactSlot {\n const title = property.title || name;\n const description = property.description;\n\n // Check if this is an array of artifacts\n if (property.type === \"array\" && property.items) {\n const items =\n typeof property.items === \"object\" && !Array.isArray(property.items)\n ? (property.items as JSONSchema7)\n : undefined;\n\n const artifactType = items?.$ref ? getArtifactType(items.$ref) : \"image\";\n\n return {\n name: title,\n fieldName: name,\n artifactType,\n required,\n description,\n isArray: true,\n minItems: property.minItems,\n maxItems: property.maxItems,\n };\n }\n\n // Single artifact\n const artifactType = property.$ref ? getArtifactType(property.$ref) : \"image\";\n\n return {\n name: title,\n fieldName: name,\n artifactType,\n required,\n description,\n isArray: false,\n };\n}\n\n/**\n * Determines if a numeric property should be rendered as a slider.\n *\n * A property is considered a slider if it's a number or integer type\n * and has both minimum and maximum values defined.\n *\n * @param property - The JSON Schema property to check\n * @returns True if this should be a slider\n */\nfunction isSlider(property: JSONSchema7): boolean {\n return (\n (property.type === \"number\" || property.type === \"integer\") &&\n property.minimum !== undefined &&\n property.maximum !== undefined\n );\n}\n\n/**\n * Parses a settings field into its appropriate type (slider, dropdown, text, number).\n *\n * @param name - The property name from the schema\n * @param property - The JSON Schema property definition\n * @returns Parsed settings field information\n */\nexport function parseSettingsField(\n name: string,\n property: JSONSchema7\n): SettingsField | null {\n const title = property.title || name;\n const description = property.description;\n\n // Dropdown (enum)\n if (property.enum && Array.isArray(property.enum)) {\n const options = property.enum.map((val) => String(val));\n const defaultValue =\n property.default !== undefined ? String(property.default) : undefined;\n\n return {\n type: \"dropdown\",\n fieldName: name,\n title,\n description,\n options,\n default: defaultValue,\n };\n }\n\n // Slider (number/integer with min/max)\n if (isSlider(property)) {\n const isInteger = property.type === \"integer\";\n return {\n type: \"slider\",\n fieldName: name,\n title,\n description,\n min: property.minimum as number,\n max: property.maximum as number,\n step: property.multipleOf,\n default:\n property.default !== undefined\n ? (property.default as number)\n : undefined,\n isInteger,\n };\n }\n\n // Number input (without slider constraints)\n if (property.type === \"number\" || property.type === \"integer\") {\n const isInteger = property.type === \"integer\";\n return {\n type: \"number\",\n fieldName: name,\n title,\n description,\n default:\n property.default !== undefined\n ? (property.default as number)\n : undefined,\n min: property.minimum as number | undefined,\n max: property.maximum as number | undefined,\n isInteger,\n };\n }\n\n // Text input\n if (property.type === \"string\") {\n return {\n type: \"text\",\n fieldName: name,\n title,\n description,\n default:\n property.default !== undefined ? String(property.default) : undefined,\n pattern: property.pattern,\n };\n }\n\n // Unsupported type\n return null;\n}\n\n/**\n * Parses a complete generator JSON Schema into structured data for UI generation.\n *\n * This function categorizes schema properties into:\n * - Artifact slots (for selecting existing artifacts)\n * - Prompt field (special text input for generation prompts)\n * - Settings fields (sliders, dropdowns, text inputs, etc.)\n *\n * @param schema - The JSON Schema from the generator's inputSchema field\n * @returns Parsed schema structure ready for dynamic UI generation\n *\n * @example\n * ```typescript\n * const generator = generators[0];\n * const parsed = parseGeneratorSchema(generator.inputSchema);\n *\n * // Render artifact slots\n * parsed.artifactSlots.forEach(slot => {\n * console.log(`${slot.name}: ${slot.artifactType} (required: ${slot.required})`);\n * });\n *\n * // Render prompt field\n * if (parsed.promptField) {\n * console.log(`Prompt: ${parsed.promptField.description}`);\n * }\n *\n * // Render settings\n * parsed.settingsFields.forEach(field => {\n * if (field.type === 'slider') {\n * console.log(`${field.title}: ${field.min} - ${field.max}`);\n * }\n * });\n * ```\n */\nexport function parseGeneratorSchema(\n schema: JSONSchema7\n): ParsedGeneratorSchema {\n const artifactSlots: ArtifactSlot[] = [];\n const settingsFields: SettingsField[] = [];\n let promptField: PromptField | null = null;\n\n if (!schema.properties) {\n return { artifactSlots, promptField, settingsFields };\n }\n\n const required = schema.required || [];\n\n for (const [name, propertyDef] of Object.entries(schema.properties)) {\n if (typeof propertyDef === \"boolean\") {\n continue;\n }\n\n const property = propertyDef as JSONSchema7;\n const isRequired = required.includes(name);\n\n // Check if this is an artifact reference\n if (isArtifactReference(property)) {\n const slot = parseArtifactSlot(name, property, isRequired);\n artifactSlots.push(slot);\n continue;\n }\n\n // Check if this is the prompt field\n if (name === \"prompt\" && property.type === \"string\") {\n promptField = {\n fieldName: name,\n description: property.description,\n required: isRequired,\n default:\n property.default !== undefined ? String(property.default) : undefined,\n };\n continue;\n }\n\n // Everything else goes to settings\n const settingsField = parseSettingsField(name, property);\n if (settingsField) {\n settingsFields.push(settingsField);\n }\n }\n\n return {\n artifactSlots,\n promptField,\n settingsFields,\n };\n}\n","/**\n * Main provider component that sets up GraphQL client and auth context.\n */\n\nimport { ReactNode } from \"react\";\nimport { Provider as UrqlProvider } from \"urql\";\nimport { createGraphQLClient } from \"../graphql/client\";\nimport { AuthProvider } from \"../auth/context\";\nimport { BaseAuthProvider } from \"../auth/providers/base\";\nimport { ApiConfigProvider, ApiConfig } from \"../config/ApiConfigContext\";\n\ninterface BoardsProviderProps {\n children: ReactNode;\n /**\n * Base URL for the backend API (e.g., \"http://localhost:8088\")\n * Used for REST endpoints like SSE streams\n */\n apiUrl: string;\n /**\n * GraphQL endpoint URL (e.g., \"http://localhost:8088/graphql\")\n * If not provided, defaults to `${apiUrl}/graphql`\n */\n graphqlUrl?: string;\n /**\n * WebSocket URL for GraphQL subscriptions\n */\n subscriptionUrl?: string;\n authProvider: BaseAuthProvider;\n tenantId?: string;\n}\n\nexport function BoardsProvider({\n children,\n apiUrl,\n graphqlUrl,\n subscriptionUrl,\n authProvider,\n tenantId,\n}: BoardsProviderProps) {\n // Default graphqlUrl if not provided\n const resolvedGraphqlUrl = graphqlUrl || `${apiUrl}/graphql`;\n\n // Create API config for hooks\n const apiConfig: ApiConfig = {\n apiUrl,\n graphqlUrl: resolvedGraphqlUrl,\n subscriptionUrl,\n };\n\n // Create the GraphQL client with auth integration\n const client = createGraphQLClient({\n url: resolvedGraphqlUrl,\n subscriptionUrl,\n auth: {\n getToken: () =>\n authProvider.getAuthState().then((state) => state.getToken()),\n },\n tenantId,\n });\n\n return (\n <AuthProvider provider={authProvider}>\n <ApiConfigProvider config={apiConfig}>\n <UrqlProvider value={client}>{children}</UrqlProvider>\n </ApiConfigProvider>\n </AuthProvider>\n );\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","createWSClient","import_urql","BoardRole","GenerationStatus","ArtifactType","import_react","import_urql","import_react","import_urql","import_react","import_urql","result","import_react","import_urql","artifactType","import_urql","import_jsx_runtime","UrqlProvider"]}
|
package/dist/index.mjs
CHANGED
|
@@ -556,9 +556,10 @@ function useBoards(options = {}) {
|
|
|
556
556
|
if (!result.data?.createBoard) {
|
|
557
557
|
throw new Error("Failed to create board");
|
|
558
558
|
}
|
|
559
|
+
reexecuteQuery({ requestPolicy: "network-only" });
|
|
559
560
|
return result.data.createBoard;
|
|
560
561
|
},
|
|
561
|
-
[createBoardMutation]
|
|
562
|
+
[createBoardMutation, reexecuteQuery]
|
|
562
563
|
);
|
|
563
564
|
const deleteBoard = useCallback2(
|
|
564
565
|
async (boardId) => {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/auth/context.tsx","../src/auth/providers/base.ts","../src/auth/providers/none.ts","../src/config/ApiConfigContext.tsx","../src/graphql/client.ts","../src/graphql/operations.ts","../src/hooks/useBoards.ts","../src/hooks/useBoard.ts","../src/hooks/useGeneration.ts","../src/hooks/useGenerators.ts","../src/utils/schemaParser.ts","../src/providers/BoardsProvider.tsx","../src/index.ts"],"sourcesContent":["/**\n * React context for authentication.\n */\n\nimport React, { createContext, useContext, useEffect, useState, useCallback } from 'react';\nimport { AuthContextValue, AuthState } from './types';\nimport { BaseAuthProvider } from './providers/base';\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\ninterface AuthProviderProps {\n provider: BaseAuthProvider;\n children: React.ReactNode;\n}\n\nexport function AuthProvider({ provider, children }: AuthProviderProps) {\n const [state, setState] = useState<AuthState>({\n user: null,\n status: 'loading',\n signIn: async () => {},\n signOut: async () => {},\n getToken: async () => null,\n refreshToken: async () => null,\n });\n const [isInitializing, setIsInitializing] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const clearError = useCallback(() => {\n setError(null);\n }, []);\n\n useEffect(() => {\n let mounted = true;\n let unsubscribe: (() => void) | null = null;\n\n const initializeAuth = async () => {\n try {\n await provider.initialize();\n\n if (!mounted) return;\n\n // Set up state change listener\n unsubscribe = provider.onAuthStateChange((newState) => {\n if (mounted) {\n setState(newState);\n }\n });\n\n // Get initial state\n const initialState = await provider.getAuthState();\n if (mounted) {\n setState(initialState);\n setIsInitializing(false);\n }\n } catch (err) {\n if (mounted) {\n setError(err instanceof Error ? err : new Error('Auth initialization failed'));\n setIsInitializing(false);\n }\n }\n };\n\n initializeAuth();\n\n return () => {\n mounted = false;\n if (unsubscribe) {\n unsubscribe();\n }\n };\n }, [provider]);\n\n // Clean up provider on unmount\n useEffect(() => {\n return () => {\n provider.destroy();\n };\n }, [provider]);\n\n const contextValue: AuthContextValue = {\n ...state,\n isInitializing,\n error,\n clearError,\n };\n\n return (\n <AuthContext.Provider value={contextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n\nexport function useAuth(): AuthContextValue {\n const context = useContext(AuthContext);\n if (!context) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n return context;\n}\n\nexport function useAuthOptional(): AuthContextValue | null {\n return useContext(AuthContext);\n}\n","/**\n * Base authentication provider abstract class.\n */\n\nimport { AuthState, User, AuthProviderConfig } from '../types';\n\nexport abstract class BaseAuthProvider {\n protected config: AuthProviderConfig;\n\n constructor(config: AuthProviderConfig = {}) {\n this.config = config;\n }\n\n /**\n * Initialize the auth provider.\n * Called once when the provider is created.\n */\n abstract initialize(): Promise<void>;\n\n /**\n * Get the current authentication state.\n */\n abstract getAuthState(): Promise<AuthState>;\n\n /**\n * Sign in with the provider.\n */\n abstract signIn(opts?: Record<string, unknown>): Promise<void>;\n\n /**\n * Sign out from the provider.\n */\n abstract signOut(): Promise<void>;\n\n /**\n * Get the current authentication token.\n */\n abstract getToken(): Promise<string | null>;\n\n /**\n * Get the current user information.\n */\n abstract getUser(): Promise<User | null>;\n\n /**\n * Listen for auth state changes.\n * Returns an unsubscribe function.\n */\n abstract onAuthStateChange(callback: (state: AuthState) => void): () => void;\n\n /**\n * Clean up resources when the provider is destroyed.\n */\n abstract destroy(): Promise<void>;\n\n /**\n * Get the tenant ID from config.\n */\n protected getTenantId(): string {\n return this.config.tenantId || 'default';\n }\n}\n","/**\n * No-auth provider for local development without authentication.\n */\n\nimport { BaseAuthProvider } from \"./base\";\nimport { AuthState, User, AuthProviderConfig } from \"../types\";\n\ninterface NoAuthConfig extends AuthProviderConfig {\n /**\n * Default user ID for development.\n * Defaults to 'dev-user'.\n */\n defaultUserId?: string;\n\n /**\n * Default user email for development.\n * Defaults to 'dev@example.com'.\n */\n defaultEmail?: string;\n\n /**\n * Default display name for development.\n * Defaults to 'Development User'.\n */\n defaultDisplayName?: string;\n}\n\nexport class NoAuthProvider extends BaseAuthProvider {\n protected config: NoAuthConfig;\n private listeners: ((state: AuthState) => void)[] = [];\n private currentState: AuthState;\n private defaultUser: User;\n\n constructor(config: NoAuthConfig = {}) {\n super(config);\n\n // Production safety check\n const nodeEnv = typeof process !== \"undefined\" ? process.env?.NODE_ENV : \"\";\n const isDevelopment =\n nodeEnv === \"development\" || nodeEnv === \"\" || nodeEnv === \"test\";\n\n if (!isDevelopment) {\n const warning =\n \"NoAuthProvider is being used in a production environment. \" +\n \"This means authentication is disabled! \" +\n \"For production use on a server that is visible to the public, configure a proper authentication provider (JWT, Supabase, Clerk, etc.)\";\n console.warn(\"⚠️ SECURITY WARNING:\", warning);\n }\n\n this.config = {\n defaultUserId: \"dev-user\",\n defaultEmail: \"dev@example.com\",\n defaultDisplayName: \"Development User\",\n ...config,\n };\n\n this.defaultUser = {\n id: this.config.defaultUserId!,\n email: this.config.defaultEmail!,\n name: this.config.defaultDisplayName,\n avatar: undefined,\n metadata: { provider: \"none\" },\n credits: {\n balance: 1000,\n reserved: 0,\n },\n };\n\n this.currentState = {\n user: this.defaultUser,\n status: \"authenticated\", // Always authenticated in no-auth mode\n signIn: this.signIn.bind(this),\n signOut: this.signOut.bind(this),\n getToken: this.getToken.bind(this),\n refreshToken: this.refreshToken.bind(this),\n };\n\n // Use structured warning instead of console.warn\n if (console.warn) {\n console.warn(\n \"🚨 [AUTH] NoAuthProvider is active - authentication is disabled!\",\n {\n message: \"This should ONLY be used in development environments\",\n environment: nodeEnv || \"unknown\",\n provider: \"none\",\n }\n );\n }\n }\n\n async initialize(): Promise<void> {\n // No initialization needed - always authenticated\n this.updateState({ user: this.defaultUser, status: \"authenticated\" });\n }\n\n async getAuthState(): Promise<AuthState> {\n return this.currentState;\n }\n\n async signIn(): Promise<void> {\n // No-op in no-auth mode - already signed in\n if (console.info) {\n console.info(\"[AUTH] SignIn called in no-auth mode - no action taken\", {\n provider: \"none\",\n action: \"signIn\",\n status: \"ignored\",\n });\n }\n }\n\n async signOut(): Promise<void> {\n // No-op in no-auth mode - can't sign out\n if (console.info) {\n console.info(\"[AUTH] SignOut called in no-auth mode - no action taken\", {\n provider: \"none\",\n action: \"signOut\",\n status: \"ignored\",\n });\n }\n }\n\n async getToken(): Promise<string | null> {\n // Return a fake development token\n return \"dev-token|no-auth-mode|always-valid\";\n }\n\n async refreshToken(): Promise<string | null> {\n // Return the same fake token since it doesn't expire\n return \"dev-token|no-auth-mode|always-valid\";\n }\n\n async getUser(): Promise<User | null> {\n return this.defaultUser;\n }\n\n onAuthStateChange(callback: (state: AuthState) => void): () => void {\n // Call immediately with current state\n callback(this.currentState);\n\n this.listeners.push(callback);\n return () => {\n const index = this.listeners.indexOf(callback);\n if (index > -1) {\n this.listeners.splice(index, 1);\n }\n };\n }\n\n async destroy(): Promise<void> {\n this.listeners = [];\n }\n\n private updateState(updates: Partial<AuthState>): void {\n this.currentState = { ...this.currentState, ...updates };\n this.listeners.forEach((listener) => listener(this.currentState));\n }\n}\n","/**\n * API configuration context for providing backend URLs to hooks.\n */\n\nimport { createContext, useContext, ReactNode } from \"react\";\n\nexport interface ApiConfig {\n /**\n * Base URL for the backend API (e.g., \"http://localhost:8088\")\n * Used for REST endpoints like SSE streams\n */\n apiUrl: string;\n /**\n * GraphQL endpoint URL (e.g., \"http://localhost:8088/graphql\")\n */\n graphqlUrl: string;\n /**\n * WebSocket URL for GraphQL subscriptions\n */\n subscriptionUrl?: string;\n}\n\nconst ApiConfigContext = createContext<ApiConfig | null>(null);\n\ninterface ApiConfigProviderProps {\n children: ReactNode;\n config: ApiConfig;\n}\n\nexport function ApiConfigProvider({\n children,\n config,\n}: ApiConfigProviderProps) {\n return (\n <ApiConfigContext.Provider value={config}>\n {children}\n </ApiConfigContext.Provider>\n );\n}\n\nexport function useApiConfig(): ApiConfig {\n const context = useContext(ApiConfigContext);\n if (!context) {\n throw new Error(\"useApiConfig must be used within ApiConfigProvider\");\n }\n return context;\n}\n","/**\n * GraphQL client configuration with authentication.\n */\n\nimport {\n createClient,\n fetchExchange,\n cacheExchange,\n subscriptionExchange,\n makeOperation,\n} from \"urql\";\nimport { authExchange } from \"@urql/exchange-auth\";\nimport { createClient as createWSClient } from \"graphql-ws\";\n\ninterface AuthState {\n getToken(): Promise<string | null>;\n}\n\ninterface ClientConfig {\n url: string;\n subscriptionUrl?: string;\n auth: AuthState;\n tenantId?: string;\n}\n\nexport function createGraphQLClient({\n url,\n subscriptionUrl,\n auth,\n tenantId,\n}: ClientConfig) {\n const wsClient = subscriptionUrl\n ? createWSClient({\n url: subscriptionUrl,\n connectionParams: async () => {\n const token = await auth.getToken();\n const headers: Record<string, string> = {};\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n if (tenantId) {\n headers[\"X-Tenant\"] = tenantId;\n }\n\n return headers;\n },\n })\n : null;\n\n return createClient({\n url,\n exchanges: [\n cacheExchange,\n authExchange(async () => {\n // Initialize auth state by fetching token\n let token = await auth.getToken();\n\n return {\n addAuthToOperation: (operation) => {\n // Build headers\n const headers: Record<string, string> = {};\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n if (tenantId) {\n headers[\"X-Tenant\"] = tenantId;\n }\n const fetchOptions =\n typeof operation.context.fetchOptions === \"function\"\n ? operation.context.fetchOptions()\n : operation.context.fetchOptions || {};\n\n // Add headers to operation context\n return makeOperation(operation.kind, operation, {\n ...operation.context,\n fetchOptions: {\n ...operation.context.fetchOptions,\n headers: {\n ...fetchOptions.headers,\n ...headers,\n },\n },\n });\n },\n\n didAuthError: (error) => {\n // Check if error is auth-related\n return error.graphQLErrors.some(\n (e) =>\n e.extensions?.code === \"UNAUTHENTICATED\" ||\n e.extensions?.code === \"UNAUTHORIZED\"\n );\n },\n\n willAuthError: () => {\n // We don't preemptively block requests\n return false;\n },\n\n refreshAuth: async () => {\n // Re-fetch token on auth error and update the closure variable\n token = await auth.getToken();\n },\n };\n }),\n fetchExchange,\n ...(wsClient\n ? [\n subscriptionExchange({\n forwardSubscription: (operation) => ({\n subscribe: (sink) => ({\n unsubscribe: wsClient.subscribe(\n {\n query: operation.query || \"\",\n variables: operation.variables,\n },\n sink\n ),\n }),\n }),\n }),\n ]\n : []),\n ],\n });\n}\n","/**\n * GraphQL queries and mutations for the Boards API.\n */\n\nimport { gql } from \"urql\";\n\n// Fragments for reusable query parts\nexport const USER_FRAGMENT = gql`\n fragment UserFragment on User {\n id\n email\n displayName\n avatarUrl\n createdAt\n }\n`;\n\nexport const BOARD_FRAGMENT = gql`\n fragment BoardFragment on Board {\n id\n tenantId\n ownerId\n title\n description\n isPublic\n settings\n metadata\n createdAt\n updatedAt\n generationCount\n }\n`;\n\nexport const GENERATION_FRAGMENT = gql`\n fragment GenerationFragment on Generation {\n id\n boardId\n userId\n generatorName\n artifactType\n status\n progress\n storageUrl\n thumbnailUrl\n inputParams\n outputMetadata\n errorMessage\n createdAt\n updatedAt\n completedAt\n }\n`;\n\n// Auth queries\nexport const GET_CURRENT_USER = gql`\n ${USER_FRAGMENT}\n query GetCurrentUser {\n me {\n ...UserFragment\n }\n }\n`;\n\n// Board queries\nexport const GET_BOARDS = gql`\n ${BOARD_FRAGMENT}\n ${USER_FRAGMENT}\n query GetBoards($limit: Int, $offset: Int) {\n myBoards(limit: $limit, offset: $offset) {\n ...BoardFragment\n owner {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const GET_BOARD = gql`\n ${BOARD_FRAGMENT}\n ${USER_FRAGMENT}\n ${GENERATION_FRAGMENT}\n query GetBoard($id: UUID!) {\n board(id: $id) {\n ...BoardFragment\n owner {\n ...UserFragment\n }\n members {\n id\n boardId\n userId\n role\n invitedBy\n joinedAt\n user {\n ...UserFragment\n }\n inviter {\n ...UserFragment\n }\n }\n generations(limit: 10) {\n ...GenerationFragment\n }\n }\n }\n`;\n\n// Generator queries\nexport const GET_GENERATORS = gql`\n query GetGenerators($artifactType: String) {\n generators(artifactType: $artifactType) {\n name\n description\n artifactType\n inputSchema\n }\n }\n`;\n\n// Generation queries\nexport const GET_GENERATIONS = gql`\n ${GENERATION_FRAGMENT}\n query GetGenerations($boardId: UUID, $limit: Int, $offset: Int) {\n generations(boardId: $boardId, limit: $limit, offset: $offset) {\n ...GenerationFragment\n board {\n id\n title\n }\n user {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const GET_GENERATION = gql`\n ${GENERATION_FRAGMENT}\n query GetGeneration($id: UUID!) {\n generation(id: $id) {\n ...GenerationFragment\n board {\n ...BoardFragment\n }\n user {\n ...UserFragment\n }\n }\n }\n`;\n\n// Board mutations\nexport const CREATE_BOARD = gql`\n ${BOARD_FRAGMENT}\n ${USER_FRAGMENT}\n mutation CreateBoard($input: CreateBoardInput!) {\n createBoard(input: $input) {\n ...BoardFragment\n owner {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const UPDATE_BOARD = gql`\n ${BOARD_FRAGMENT}\n mutation UpdateBoard($id: UUID!, $input: UpdateBoardInput!) {\n updateBoard(id: $id, input: $input) {\n ...BoardFragment\n }\n }\n`;\n\nexport const DELETE_BOARD = gql`\n mutation DeleteBoard($id: UUID!) {\n deleteBoard(id: $id) {\n success\n }\n }\n`;\n\n// Board member mutations\nexport const ADD_BOARD_MEMBER = gql`\n mutation AddBoardMember($boardId: UUID!, $email: String!, $role: BoardRole!) {\n addBoardMember(boardId: $boardId, email: $email, role: $role) {\n id\n boardId\n userId\n role\n invitedBy\n joinedAt\n user {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const UPDATE_BOARD_MEMBER_ROLE = gql`\n mutation UpdateBoardMemberRole($id: UUID!, $role: BoardRole!) {\n updateBoardMemberRole(id: $id, role: $role) {\n id\n role\n }\n }\n`;\n\nexport const REMOVE_BOARD_MEMBER = gql`\n mutation RemoveBoardMember($id: UUID!) {\n removeBoardMember(id: $id) {\n success\n }\n }\n`;\n\n// Generation mutations\nexport const CREATE_GENERATION = gql`\n ${GENERATION_FRAGMENT}\n mutation CreateGeneration($input: CreateGenerationInput!) {\n createGeneration(input: $input) {\n ...GenerationFragment\n }\n }\n`;\n\nexport const CANCEL_GENERATION = gql`\n mutation CancelGeneration($id: UUID!) {\n cancelGeneration(id: $id) {\n id\n status\n }\n }\n`;\n\nexport const RETRY_GENERATION = gql`\n ${GENERATION_FRAGMENT}\n mutation RetryGeneration($id: UUID!) {\n retryGeneration(id: $id) {\n ...GenerationFragment\n }\n }\n`;\n\n// Input types (these should match your backend GraphQL schema)\nexport interface CreateBoardInput {\n title: string;\n description?: string;\n isPublic?: boolean;\n settings?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UpdateBoardInput {\n title?: string;\n description?: string;\n isPublic?: boolean;\n settings?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CreateGenerationInput {\n boardId: string;\n generatorName: string;\n artifactType: ArtifactType; // Allow string for flexibility with new types\n inputParams: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\n// Enums (should match backend)\nexport enum BoardRole {\n VIEWER = \"VIEWER\",\n EDITOR = \"EDITOR\",\n ADMIN = \"ADMIN\",\n}\n\nexport enum GenerationStatus {\n PENDING = \"PENDING\",\n RUNNING = \"RUNNING\",\n COMPLETED = \"COMPLETED\",\n FAILED = \"FAILED\",\n CANCELLED = \"CANCELLED\",\n}\n\nexport enum ArtifactType {\n IMAGE = \"image\",\n VIDEO = \"video\",\n AUDIO = \"audio\",\n TEXT = \"text\",\n LORA = \"lora\",\n MODEL = \"model\",\n}\n","/**\n * Hook for managing multiple boards.\n */\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport { useQuery, useMutation } from \"urql\";\n// import { Cache } from '@urql/core';\nimport {\n GET_BOARDS,\n CREATE_BOARD,\n DELETE_BOARD,\n CreateBoardInput,\n} from \"../graphql/operations\";\n\ninterface Board {\n id: string;\n tenantId: string;\n ownerId: string;\n title: string;\n description?: string;\n isPublic: boolean;\n settings: Record<string, unknown>;\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n generationCount: number;\n owner: {\n id: string;\n email: string;\n displayName: string;\n avatarUrl?: string;\n createdAt: string;\n };\n}\n\ninterface UseBoardsOptions {\n limit?: number;\n offset?: number;\n}\n\ninterface BoardsHook {\n boards: Board[];\n loading: boolean;\n error: Error | null;\n createBoard: (data: CreateBoardInput) => Promise<Board>;\n deleteBoard: (boardId: string) => Promise<void>;\n searchBoards: (query: string) => Promise<Board[]>;\n refresh: () => Promise<void>;\n setSearchQuery: (query: string) => void;\n searchQuery: string;\n}\n\nexport function useBoards(options: UseBoardsOptions = {}): BoardsHook {\n const { limit = 50, offset = 0 } = options;\n const [searchQuery, setSearchQuery] = useState(\"\");\n\n // Query for boards\n const [{ data, fetching, error }, reexecuteQuery] = useQuery({\n query: GET_BOARDS,\n variables: { limit, offset },\n });\n\n // Mutations\n const [, createBoardMutation] = useMutation(CREATE_BOARD);\n const [, deleteBoardMutation] = useMutation(DELETE_BOARD);\n\n const boards = useMemo(() => data?.myBoards || [], [data?.myBoards]);\n\n const createBoard = useCallback(\n async (input: CreateBoardInput): Promise<Board> => {\n const result = await createBoardMutation({ input });\n if (result.error) {\n throw new Error(result.error.message);\n }\n if (!result.data?.createBoard) {\n throw new Error(\"Failed to create board\");\n }\n return result.data.createBoard;\n },\n [createBoardMutation]\n );\n\n const deleteBoard = useCallback(\n async (boardId: string): Promise<void> => {\n const result = await deleteBoardMutation({ id: boardId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.deleteBoard?.success) {\n throw new Error(\"Failed to delete board\");\n }\n reexecuteQuery({ requestPolicy: \"network-only\" });\n },\n [deleteBoardMutation, reexecuteQuery]\n );\n\n const searchBoards = useCallback(\n async (query: string): Promise<Board[]> => {\n // Set search query which will trigger debounced search via useEffect\n setSearchQuery(query);\n\n // Return promise that resolves when search completes\n // This is a simplified implementation - in a real app you might want\n // to return the actual search results from the API\n return new Promise((resolve) => {\n // Wait for debounce delay plus a bit more for API response\n setTimeout(() => {\n resolve(\n boards.filter(\n (board: Board) =>\n board.title.toLowerCase().includes(query.toLowerCase()) ||\n board.description?.toLowerCase().includes(query.toLowerCase())\n )\n );\n }, 350);\n });\n },\n [boards]\n );\n\n const refresh = useCallback(async (): Promise<void> => {\n await reexecuteQuery({ requestPolicy: \"network-only\" });\n }, [reexecuteQuery]);\n\n return {\n boards,\n loading: fetching,\n error: error ? new Error(error.message) : null,\n createBoard,\n deleteBoard,\n searchBoards,\n refresh,\n setSearchQuery,\n searchQuery,\n };\n}\n","/**\n * Hook for managing a single board.\n */\n\nimport { useCallback, useMemo } from \"react\";\nimport { useQuery, useMutation } from \"urql\";\nimport { useAuth } from \"../auth/hooks/useAuth\";\nimport {\n GET_BOARD,\n UPDATE_BOARD,\n DELETE_BOARD,\n ADD_BOARD_MEMBER,\n UPDATE_BOARD_MEMBER_ROLE,\n REMOVE_BOARD_MEMBER,\n UpdateBoardInput,\n BoardRole,\n} from \"../graphql/operations\";\n\ninterface User {\n id: string;\n email: string;\n displayName: string;\n avatarUrl?: string;\n createdAt: string;\n}\n\ninterface BoardMember {\n id: string;\n boardId: string;\n userId: string;\n role: BoardRole;\n invitedBy?: string;\n joinedAt: string;\n user: User;\n inviter?: User;\n}\n\ninterface Generation {\n id: string;\n boardId: string;\n userId: string;\n generatorName: string;\n artifactType: string;\n status: string;\n progress: number;\n storageUrl?: string | null;\n thumbnailUrl?: string | null;\n inputParams: Record<string, unknown>;\n outputMetadata: Record<string, unknown>;\n errorMessage?: string | null;\n createdAt: string;\n updatedAt: string;\n completedAt?: string | null;\n}\n\ninterface Board {\n id: string;\n tenantId: string;\n ownerId: string;\n title: string;\n description?: string;\n isPublic: boolean;\n settings: Record<string, unknown>;\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n generationCount: number;\n owner: User;\n members: BoardMember[];\n generations: Generation[];\n}\n\ntype MemberRole = BoardRole;\n\ninterface BoardPermissions {\n canEdit: boolean;\n canDelete: boolean;\n canAddMembers: boolean;\n canRemoveMembers: boolean;\n canGenerate: boolean;\n canExport: boolean;\n}\n\ninterface ShareLinkOptions {\n expiresIn?: number;\n permissions?: string[];\n}\n\ninterface ShareLink {\n id: string;\n url: string;\n expiresAt?: string;\n permissions: string[];\n}\n\ninterface BoardHook {\n board: Board | null;\n members: BoardMember[];\n permissions: BoardPermissions;\n loading: boolean;\n error: Error | null;\n\n // Board operations\n updateBoard: (updates: Partial<UpdateBoardInput>) => Promise<Board>;\n deleteBoard: () => Promise<void>;\n refresh: () => Promise<void>;\n\n // Member management\n addMember: (email: string, role: MemberRole) => Promise<BoardMember>;\n removeMember: (memberId: string) => Promise<void>;\n updateMemberRole: (\n memberId: string,\n role: MemberRole\n ) => Promise<BoardMember>;\n\n // Sharing (placeholder - would need backend implementation)\n generateShareLink: (options: ShareLinkOptions) => Promise<ShareLink>;\n revokeShareLink: (linkId: string) => Promise<void>;\n}\n\nexport function useBoard(boardId: string): BoardHook {\n const { user } = useAuth();\n\n // Query for board data\n const [{ data, fetching, error }, reexecuteQuery] = useQuery({\n query: GET_BOARD,\n variables: { id: boardId },\n pause: !boardId,\n requestPolicy: \"cache-and-network\", // Always fetch fresh data while showing cached data\n });\n\n // Mutations\n const [, updateBoardMutation] = useMutation(UPDATE_BOARD);\n const [, deleteBoardMutation] = useMutation(DELETE_BOARD);\n const [, addMemberMutation] = useMutation(ADD_BOARD_MEMBER);\n const [, updateMemberRoleMutation] = useMutation(UPDATE_BOARD_MEMBER_ROLE);\n const [, removeMemberMutation] = useMutation(REMOVE_BOARD_MEMBER);\n\n const board = useMemo(() => data?.board || null, [data?.board]);\n const members = useMemo(() => board?.members || [], [board?.members]);\n\n // Calculate permissions based on user role\n const permissions = useMemo((): BoardPermissions => {\n if (!board || !user) {\n return {\n canEdit: false,\n canDelete: false,\n canAddMembers: false,\n canRemoveMembers: false,\n canGenerate: false,\n canExport: false,\n };\n }\n\n // Check if user is the board owner\n const isOwner = board.ownerId === user.id;\n\n // Find user's role in board members\n const userMember = members.find(\n (member: BoardMember) => member.userId === user.id\n );\n const userRole = userMember?.role;\n\n const isAdmin = userRole === BoardRole.ADMIN;\n const isEditor = userRole === BoardRole.EDITOR || isAdmin;\n const isViewer = userRole === BoardRole.VIEWER || isEditor;\n\n return {\n canEdit: isOwner || isAdmin || isEditor,\n canDelete: isOwner,\n canAddMembers: isOwner || isAdmin,\n canRemoveMembers: isOwner || isAdmin,\n canGenerate: isOwner || isAdmin || isEditor,\n canExport: isViewer, // Even viewers can export\n };\n }, [board, user, members]);\n\n const updateBoard = useCallback(\n async (updates: Partial<UpdateBoardInput>): Promise<Board> => {\n if (!boardId) {\n throw new Error(\"Board ID is required\");\n }\n\n const result = await updateBoardMutation({\n id: boardId,\n input: updates,\n });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.updateBoard) {\n throw new Error(\"Failed to update board\");\n }\n\n return result.data.updateBoard;\n },\n [boardId, updateBoardMutation]\n );\n\n const deleteBoard = useCallback(async (): Promise<void> => {\n if (!boardId) {\n throw new Error(\"Board ID is required\");\n }\n\n const result = await deleteBoardMutation({ id: boardId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.deleteBoard?.success) {\n throw new Error(\"Failed to delete board\");\n }\n }, [boardId, deleteBoardMutation]);\n\n const addMember = useCallback(\n async (email: string, role: MemberRole): Promise<BoardMember> => {\n if (!boardId) {\n throw new Error(\"Board ID is required\");\n }\n\n const result = await addMemberMutation({\n boardId,\n email,\n role,\n });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.addBoardMember) {\n throw new Error(\"Failed to add member\");\n }\n\n // Refresh board data to get updated members list\n reexecuteQuery({ requestPolicy: \"network-only\" });\n\n return result.data.addBoardMember;\n },\n [boardId, addMemberMutation, reexecuteQuery]\n );\n\n const removeMember = useCallback(\n async (memberId: string): Promise<void> => {\n const result = await removeMemberMutation({ id: memberId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.removeBoardMember?.success) {\n throw new Error(\"Failed to remove member\");\n }\n\n // Refresh board data to get updated members list\n reexecuteQuery({ requestPolicy: \"network-only\" });\n },\n [removeMemberMutation, reexecuteQuery]\n );\n\n const updateMemberRole = useCallback(\n async (memberId: string, role: MemberRole): Promise<BoardMember> => {\n const result = await updateMemberRoleMutation({\n id: memberId,\n role,\n });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.updateBoardMemberRole) {\n throw new Error(\"Failed to update member role\");\n }\n\n // Refresh board data to get updated members list\n reexecuteQuery({ requestPolicy: \"network-only\" });\n\n return result.data.updateBoardMemberRole;\n },\n [updateMemberRoleMutation, reexecuteQuery]\n );\n\n // Placeholder implementations for sharing features\n const generateShareLink = useCallback(\n async (_options: ShareLinkOptions): Promise<ShareLink> => {\n // TODO: Implement share link generation\n throw new Error(\"Share links not implemented yet\");\n },\n []\n );\n\n const revokeShareLink = useCallback(\n async (_linkId: string): Promise<void> => {\n // TODO: Implement share link revocation\n throw new Error(\"Share link revocation not implemented yet\");\n },\n []\n );\n\n const refresh = useCallback(async (): Promise<void> => {\n await reexecuteQuery({ requestPolicy: \"network-only\" });\n }, [reexecuteQuery]);\n\n return {\n board,\n members,\n permissions,\n loading: fetching,\n error: error ? new Error(error.message) : null,\n updateBoard,\n deleteBoard,\n refresh,\n addMember,\n removeMember,\n updateMemberRole,\n generateShareLink,\n revokeShareLink,\n };\n}\n","/**\n * Hook for managing AI generations with real-time progress via SSE.\n */\n\nimport { useCallback, useState, useEffect, useRef } from \"react\";\nimport { fetchEventSource } from \"@microsoft/fetch-event-source\";\nimport { useMutation } from \"urql\";\nimport {\n CREATE_GENERATION,\n CANCEL_GENERATION,\n RETRY_GENERATION,\n CreateGenerationInput,\n ArtifactType,\n} from \"../graphql/operations\";\nimport { useAuth } from \"../auth/context\";\nimport { useApiConfig } from \"../config/ApiConfigContext\";\n\nexport interface GenerationRequest {\n model: string;\n artifactType: ArtifactType; // Allow string for flexibility with new types\n inputs: GenerationInputs;\n boardId: string;\n options?: GenerationOptions;\n}\n\nexport interface GenerationInputs {\n prompt: string;\n negativePrompt?: string;\n image?: string | File;\n mask?: string | File;\n loras?: LoRAInput[];\n seed?: number;\n steps?: number;\n guidance?: number;\n aspectRatio?: string;\n style?: string;\n [key: string]: unknown;\n}\n\nexport interface GenerationOptions {\n priority?: \"low\" | \"normal\" | \"high\";\n timeout?: number;\n webhookUrl?: string;\n [key: string]: unknown;\n}\n\nexport interface LoRAInput {\n id: string;\n weight: number;\n}\n\nexport interface GenerationProgress {\n jobId: string;\n status: \"queued\" | \"processing\" | \"completed\" | \"failed\" | \"cancelled\";\n progress: number; // 0-100\n phase: string;\n message?: string | null;\n estimatedTimeRemaining?: number;\n currentStep?: string;\n logs?: string[];\n}\n\nexport interface GenerationResult {\n id: string;\n jobId: string;\n boardId: string;\n request: GenerationRequest;\n artifacts: Artifact[];\n credits: {\n cost: number;\n balanceBefore: number;\n balance: number;\n };\n performance: {\n queueTime: number;\n processingTime: number;\n totalTime: number;\n };\n createdAt: Date;\n}\n\nexport interface Artifact {\n id: string;\n type: string;\n url: string;\n thumbnailUrl?: string;\n metadata: Record<string, unknown>;\n}\n\nexport interface GenerationHook {\n // Current generation state\n progress: GenerationProgress | null;\n result: GenerationResult | null;\n error: Error | null;\n isGenerating: boolean;\n\n // Operations\n submit: (request: GenerationRequest) => Promise<string>;\n cancel: (jobId: string) => Promise<void>;\n retry: (jobId: string) => Promise<void>;\n\n // History\n history: GenerationResult[];\n clearHistory: () => void;\n}\n\nexport function useGeneration(): GenerationHook {\n const [progress, setProgress] = useState<GenerationProgress | null>(null);\n const [result, setResult] = useState<GenerationResult | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [isGenerating, setIsGenerating] = useState(false);\n const [history, setHistory] = useState<GenerationResult[]>([]);\n\n // Get API configuration and auth\n const { apiUrl } = useApiConfig();\n const auth = useAuth();\n\n // Keep track of active SSE connections (using AbortControllers)\n const abortControllers = useRef<Map<string, AbortController>>(new Map());\n\n // Mutations\n const [, createGenerationMutation] = useMutation(CREATE_GENERATION);\n const [, cancelGenerationMutation] = useMutation(CANCEL_GENERATION);\n const [, retryGenerationMutation] = useMutation(RETRY_GENERATION);\n\n // Clean up SSE connections on unmount\n useEffect(() => {\n return () => {\n abortControllers.current.forEach((controller) => {\n controller.abort();\n });\n abortControllers.current.clear();\n };\n }, []);\n\n const connectToSSE = useCallback(\n async (jobId: string) => {\n // Close existing connection if any\n const existingController = abortControllers.current.get(jobId);\n if (existingController) {\n existingController.abort();\n }\n\n // Create new abort controller\n const abortController = new AbortController();\n abortControllers.current.set(jobId, abortController);\n\n // Get auth token\n const token = await auth.getToken();\n\n // Build headers\n const headers: Record<string, string> = {\n Accept: \"text/event-stream\",\n };\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n // Connect to SSE endpoint directly\n const sseUrl = `${apiUrl}/api/sse/generations/${jobId}/progress`;\n console.log(\"SSE: Connecting to\", sseUrl, \"with headers:\", headers);\n\n try {\n await fetchEventSource(sseUrl, {\n headers,\n signal: abortController.signal,\n\n async onopen(response) {\n console.log(\n \"SSE: Connection opened\",\n response.status,\n response.statusText\n );\n if (response.ok) {\n console.log(\"SSE: Connection successful\");\n } else {\n console.error(\"SSE: Connection failed\", response.status);\n throw new Error(`SSE connection failed: ${response.statusText}`);\n }\n },\n\n onmessage(event) {\n console.log(\"SSE: Raw event received:\", event);\n\n // Skip empty messages (like keep-alive comments)\n if (!event.data || event.data.trim() === \"\") {\n console.log(\"SSE: Skipping empty message\");\n return;\n }\n\n try {\n const progressData: GenerationProgress = JSON.parse(event.data);\n console.log(\"SSE: progress data received:\", progressData);\n setProgress(progressData);\n\n // If generation is complete, handle the result\n if (\n progressData.status === \"completed\" ||\n progressData.status === \"failed\" ||\n progressData.status === \"cancelled\"\n ) {\n setIsGenerating(false);\n\n if (progressData.status === \"completed\") {\n // TODO: Fetch the complete result from GraphQL\n // For now, create a mock result\n const mockResult: GenerationResult = {\n id: progressData.jobId,\n jobId: progressData.jobId,\n boardId: \"\", // Would be filled from the original request\n request: {} as GenerationRequest,\n artifacts: [],\n credits: { cost: 0, balanceBefore: 0, balance: 0 },\n performance: {\n queueTime: 0,\n processingTime: 0,\n totalTime: 0,\n },\n createdAt: new Date(),\n };\n\n setResult(mockResult);\n setHistory((prev) => [...prev, mockResult]);\n } else if (progressData.status === \"failed\") {\n setError(new Error(\"Generation failed\"));\n }\n\n // Close connection\n abortController.abort();\n abortControllers.current.delete(jobId);\n }\n } catch (err) {\n console.error(\"Failed to parse SSE message:\", err);\n setError(new Error(\"Failed to parse progress update\"));\n setIsGenerating(false);\n abortController.abort();\n abortControllers.current.delete(jobId);\n }\n },\n\n onerror(err) {\n console.error(\"SSE connection error:\", err);\n console.error(\"SSE error details:\", {\n message: err instanceof Error ? err.message : String(err),\n jobId,\n url: sseUrl,\n });\n setError(new Error(\"Lost connection to generation progress\"));\n setIsGenerating(false);\n abortController.abort();\n abortControllers.current.delete(jobId);\n // Re-throw to stop retry\n throw err;\n },\n\n openWhenHidden: true, // Keep connection open when tab is hidden\n });\n } catch (err) {\n // Connection was aborted or failed\n if (abortController.signal.aborted) {\n console.log(\"SSE connection aborted for job:\", jobId);\n } else {\n console.error(\"SSE connection failed:\", err);\n }\n }\n },\n [apiUrl, auth]\n );\n\n const submit = useCallback(\n async (request: GenerationRequest): Promise<string> => {\n setError(null);\n setProgress(null);\n setResult(null);\n setIsGenerating(true);\n\n // Convert the request to the GraphQL input format\n const input: CreateGenerationInput = {\n boardId: request.boardId,\n generatorName: request.model,\n artifactType: request.artifactType,\n inputParams: {\n ...request.inputs,\n ...request.options,\n },\n };\n\n // Retry logic for generation submission\n let lastError: Error | null = null;\n const maxRetries = 2; // Fewer retries for generation as it's expensive\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n // Submit generation via GraphQL\n const result = await createGenerationMutation({ input });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.createGeneration) {\n throw new Error(\"Failed to create generation\");\n }\n\n const jobId = result.data.createGeneration.id;\n\n // Connect to SSE for progress updates\n connectToSSE(jobId);\n\n // Re-enable the submit button now that submission is complete\n // The SSE connection will continue tracking progress in the background\n setIsGenerating(false);\n\n return jobId;\n } catch (err) {\n lastError =\n err instanceof Error\n ? err\n : new Error(\"Failed to submit generation\");\n\n // Don't retry on certain types of errors\n if (\n lastError.message.includes(\"insufficient credits\") ||\n lastError.message.includes(\"validation\") ||\n lastError.message.includes(\"unauthorized\") ||\n lastError.message.includes(\"forbidden\")\n ) {\n setError(lastError);\n setIsGenerating(false);\n throw lastError;\n }\n\n // If this was the last attempt, throw the error\n if (attempt === maxRetries) {\n setError(lastError);\n setIsGenerating(false);\n throw lastError;\n }\n\n // Wait before retrying (shorter delay for generations)\n await new Promise((resolve) => setTimeout(resolve, 1000 * attempt));\n }\n }\n\n const finalError =\n lastError || new Error(\"Failed to submit generation after retries\");\n setError(finalError);\n setIsGenerating(false);\n throw finalError;\n },\n [createGenerationMutation, connectToSSE]\n );\n\n const cancel = useCallback(\n async (jobId: string): Promise<void> => {\n try {\n // Cancel via GraphQL\n const result = await cancelGenerationMutation({ id: jobId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n // Close SSE connection\n const controller = abortControllers.current.get(jobId);\n if (controller) {\n controller.abort();\n abortControllers.current.delete(jobId);\n }\n\n setIsGenerating(false);\n setProgress((prev) => (prev ? { ...prev, status: \"cancelled\" } : null));\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to cancel generation\")\n );\n }\n },\n [cancelGenerationMutation]\n );\n\n const retry = useCallback(\n async (jobId: string): Promise<void> => {\n try {\n setError(null);\n setIsGenerating(true);\n\n // Retry via GraphQL\n const result = await retryGenerationMutation({ id: jobId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.retryGeneration) {\n throw new Error(\"Failed to retry generation\");\n }\n\n const newJobId = result.data.retryGeneration.id;\n\n // Connect to SSE for the retried job\n connectToSSE(newJobId);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to retry generation\")\n );\n setIsGenerating(false);\n }\n },\n [retryGenerationMutation, connectToSSE]\n );\n\n const clearHistory = useCallback(() => {\n setHistory([]);\n }, []);\n\n return {\n progress,\n result,\n error,\n isGenerating,\n submit,\n cancel,\n retry,\n history,\n clearHistory,\n };\n}\n","/**\n * Hook for fetching available generators.\n */\n\nimport { useMemo } from \"react\";\nimport { useQuery } from \"urql\";\nimport type { JSONSchema7 } from \"json-schema\";\nimport { ArtifactType, GET_GENERATORS } from \"../graphql/operations\";\n\nexport interface Generator {\n name: string;\n description: string;\n artifactType: ArtifactType;\n inputSchema: JSONSchema7;\n}\n\n// Re-export JSONSchema7 for applications\nexport type { JSONSchema7 } from \"json-schema\";\n\ninterface UseGeneratorsOptions {\n artifactType?: string;\n}\n\ninterface GeneratorsHook {\n generators: Generator[];\n loading: boolean;\n error: Error | null;\n}\n\nexport function useGenerators(\n options: UseGeneratorsOptions = {}\n): GeneratorsHook {\n const { artifactType } = options;\n\n // Query for generators\n const [{ data, fetching, error }] = useQuery({\n query: GET_GENERATORS,\n variables: artifactType ? { artifactType } : {},\n });\n\n const generators = useMemo(() => data?.generators || [], [data?.generators]);\n\n return {\n generators,\n loading: fetching,\n error: error ? new Error(error.message) : null,\n };\n}\n","/**\n * Utilities for parsing generator JSON Schemas into structured data\n * suitable for dynamic UI generation.\n */\n\nimport type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport type {\n ParsedGeneratorSchema,\n ArtifactSlot,\n PromptField,\n SettingsField,\n} from \"../types/generatorSchema\";\n\n/**\n * Checks if a JSON Schema property references an artifact type.\n *\n * Artifacts are identified by $ref paths containing \"Artifact\" in their name,\n * e.g., \"#/$defs/AudioArtifact\" or \"#/$defs/VideoArtifact\".\n *\n * @param property - The JSON Schema property to check\n * @returns True if the property references an artifact type\n */\nexport function isArtifactReference(\n property: JSONSchema7 | JSONSchema7Definition | undefined\n): boolean {\n if (!property || typeof property === \"boolean\") {\n return false;\n }\n\n // Direct $ref to artifact\n if (property.$ref && property.$ref.includes(\"Artifact\")) {\n return true;\n }\n\n // Array with items that reference an artifact\n if (\n property.type === \"array\" &&\n property.items &&\n typeof property.items === \"object\" &&\n !Array.isArray(property.items)\n ) {\n const items = property.items as JSONSchema7;\n return !!(items.$ref && items.$ref.includes(\"Artifact\"));\n }\n\n return false;\n}\n\n/**\n * Extracts the artifact type from a $ref path.\n *\n * Examples:\n * - \"#/$defs/AudioArtifact\" -> \"audio\"\n * - \"#/$defs/VideoArtifact\" -> \"video\"\n * - \"#/$defs/ImageArtifact\" -> \"image\"\n * - \"#/$defs/TextArtifact\" -> \"text\"\n *\n * @param ref - The $ref string from the JSON Schema\n * @returns The artifact type in lowercase\n */\nexport function getArtifactType(\n ref: string\n): \"audio\" | \"video\" | \"image\" | \"text\" {\n const match = ref.match(/(Audio|Video|Image|Text)Artifact/);\n if (match) {\n return match[1].toLowerCase() as \"audio\" | \"video\" | \"image\" | \"text\";\n }\n\n // Fallback to \"image\" if pattern doesn't match\n return \"image\";\n}\n\n/**\n * Parses an artifact property into an ArtifactSlot structure.\n *\n * @param name - The property name from the schema\n * @param property - The JSON Schema property definition\n * @param required - Whether this field is in the required array\n * @returns Parsed artifact slot information\n */\nexport function parseArtifactSlot(\n name: string,\n property: JSONSchema7,\n required: boolean\n): ArtifactSlot {\n const title = property.title || name;\n const description = property.description;\n\n // Check if this is an array of artifacts\n if (property.type === \"array\" && property.items) {\n const items =\n typeof property.items === \"object\" && !Array.isArray(property.items)\n ? (property.items as JSONSchema7)\n : undefined;\n\n const artifactType = items?.$ref ? getArtifactType(items.$ref) : \"image\";\n\n return {\n name: title,\n fieldName: name,\n artifactType,\n required,\n description,\n isArray: true,\n minItems: property.minItems,\n maxItems: property.maxItems,\n };\n }\n\n // Single artifact\n const artifactType = property.$ref ? getArtifactType(property.$ref) : \"image\";\n\n return {\n name: title,\n fieldName: name,\n artifactType,\n required,\n description,\n isArray: false,\n };\n}\n\n/**\n * Determines if a numeric property should be rendered as a slider.\n *\n * A property is considered a slider if it's a number or integer type\n * and has both minimum and maximum values defined.\n *\n * @param property - The JSON Schema property to check\n * @returns True if this should be a slider\n */\nfunction isSlider(property: JSONSchema7): boolean {\n return (\n (property.type === \"number\" || property.type === \"integer\") &&\n property.minimum !== undefined &&\n property.maximum !== undefined\n );\n}\n\n/**\n * Parses a settings field into its appropriate type (slider, dropdown, text, number).\n *\n * @param name - The property name from the schema\n * @param property - The JSON Schema property definition\n * @returns Parsed settings field information\n */\nexport function parseSettingsField(\n name: string,\n property: JSONSchema7\n): SettingsField | null {\n const title = property.title || name;\n const description = property.description;\n\n // Dropdown (enum)\n if (property.enum && Array.isArray(property.enum)) {\n const options = property.enum.map((val) => String(val));\n const defaultValue =\n property.default !== undefined ? String(property.default) : undefined;\n\n return {\n type: \"dropdown\",\n fieldName: name,\n title,\n description,\n options,\n default: defaultValue,\n };\n }\n\n // Slider (number/integer with min/max)\n if (isSlider(property)) {\n const isInteger = property.type === \"integer\";\n return {\n type: \"slider\",\n fieldName: name,\n title,\n description,\n min: property.minimum as number,\n max: property.maximum as number,\n step: property.multipleOf,\n default:\n property.default !== undefined\n ? (property.default as number)\n : undefined,\n isInteger,\n };\n }\n\n // Number input (without slider constraints)\n if (property.type === \"number\" || property.type === \"integer\") {\n const isInteger = property.type === \"integer\";\n return {\n type: \"number\",\n fieldName: name,\n title,\n description,\n default:\n property.default !== undefined\n ? (property.default as number)\n : undefined,\n min: property.minimum as number | undefined,\n max: property.maximum as number | undefined,\n isInteger,\n };\n }\n\n // Text input\n if (property.type === \"string\") {\n return {\n type: \"text\",\n fieldName: name,\n title,\n description,\n default:\n property.default !== undefined ? String(property.default) : undefined,\n pattern: property.pattern,\n };\n }\n\n // Unsupported type\n return null;\n}\n\n/**\n * Parses a complete generator JSON Schema into structured data for UI generation.\n *\n * This function categorizes schema properties into:\n * - Artifact slots (for selecting existing artifacts)\n * - Prompt field (special text input for generation prompts)\n * - Settings fields (sliders, dropdowns, text inputs, etc.)\n *\n * @param schema - The JSON Schema from the generator's inputSchema field\n * @returns Parsed schema structure ready for dynamic UI generation\n *\n * @example\n * ```typescript\n * const generator = generators[0];\n * const parsed = parseGeneratorSchema(generator.inputSchema);\n *\n * // Render artifact slots\n * parsed.artifactSlots.forEach(slot => {\n * console.log(`${slot.name}: ${slot.artifactType} (required: ${slot.required})`);\n * });\n *\n * // Render prompt field\n * if (parsed.promptField) {\n * console.log(`Prompt: ${parsed.promptField.description}`);\n * }\n *\n * // Render settings\n * parsed.settingsFields.forEach(field => {\n * if (field.type === 'slider') {\n * console.log(`${field.title}: ${field.min} - ${field.max}`);\n * }\n * });\n * ```\n */\nexport function parseGeneratorSchema(\n schema: JSONSchema7\n): ParsedGeneratorSchema {\n const artifactSlots: ArtifactSlot[] = [];\n const settingsFields: SettingsField[] = [];\n let promptField: PromptField | null = null;\n\n if (!schema.properties) {\n return { artifactSlots, promptField, settingsFields };\n }\n\n const required = schema.required || [];\n\n for (const [name, propertyDef] of Object.entries(schema.properties)) {\n if (typeof propertyDef === \"boolean\") {\n continue;\n }\n\n const property = propertyDef as JSONSchema7;\n const isRequired = required.includes(name);\n\n // Check if this is an artifact reference\n if (isArtifactReference(property)) {\n const slot = parseArtifactSlot(name, property, isRequired);\n artifactSlots.push(slot);\n continue;\n }\n\n // Check if this is the prompt field\n if (name === \"prompt\" && property.type === \"string\") {\n promptField = {\n fieldName: name,\n description: property.description,\n required: isRequired,\n default:\n property.default !== undefined ? String(property.default) : undefined,\n };\n continue;\n }\n\n // Everything else goes to settings\n const settingsField = parseSettingsField(name, property);\n if (settingsField) {\n settingsFields.push(settingsField);\n }\n }\n\n return {\n artifactSlots,\n promptField,\n settingsFields,\n };\n}\n","/**\n * Main provider component that sets up GraphQL client and auth context.\n */\n\nimport { ReactNode } from \"react\";\nimport { Provider as UrqlProvider } from \"urql\";\nimport { createGraphQLClient } from \"../graphql/client\";\nimport { AuthProvider } from \"../auth/context\";\nimport { BaseAuthProvider } from \"../auth/providers/base\";\nimport { ApiConfigProvider, ApiConfig } from \"../config/ApiConfigContext\";\n\ninterface BoardsProviderProps {\n children: ReactNode;\n /**\n * Base URL for the backend API (e.g., \"http://localhost:8088\")\n * Used for REST endpoints like SSE streams\n */\n apiUrl: string;\n /**\n * GraphQL endpoint URL (e.g., \"http://localhost:8088/graphql\")\n * If not provided, defaults to `${apiUrl}/graphql`\n */\n graphqlUrl?: string;\n /**\n * WebSocket URL for GraphQL subscriptions\n */\n subscriptionUrl?: string;\n authProvider: BaseAuthProvider;\n tenantId?: string;\n}\n\nexport function BoardsProvider({\n children,\n apiUrl,\n graphqlUrl,\n subscriptionUrl,\n authProvider,\n tenantId,\n}: BoardsProviderProps) {\n // Default graphqlUrl if not provided\n const resolvedGraphqlUrl = graphqlUrl || `${apiUrl}/graphql`;\n\n // Create API config for hooks\n const apiConfig: ApiConfig = {\n apiUrl,\n graphqlUrl: resolvedGraphqlUrl,\n subscriptionUrl,\n };\n\n // Create the GraphQL client with auth integration\n const client = createGraphQLClient({\n url: resolvedGraphqlUrl,\n subscriptionUrl,\n auth: {\n getToken: () =>\n authProvider.getAuthState().then((state) => state.getToken()),\n },\n tenantId,\n });\n\n return (\n <AuthProvider provider={authProvider}>\n <ApiConfigProvider config={apiConfig}>\n <UrqlProvider value={client}>{children}</UrqlProvider>\n </ApiConfigProvider>\n </AuthProvider>\n );\n}\n","export const VERSION = \"0.1.0\";\n\n// Core auth exports\nexport * from \"./auth/types\";\nexport * from \"./auth/hooks/useAuth\";\nexport { AuthProvider } from \"./auth/context\";\nexport { BaseAuthProvider } from \"./auth/providers/base\";\nexport { NoAuthProvider } from \"./auth/providers/none\"; // Only no-auth included for dev\n\n// API configuration\nexport { useApiConfig } from \"./config/ApiConfigContext\";\nexport type { ApiConfig } from \"./config/ApiConfigContext\";\n\n// GraphQL exports\nexport { createGraphQLClient } from \"./graphql/client\";\nexport * from \"./graphql/operations\";\n\n// Core hooks\nexport { useBoards } from \"./hooks/useBoards\";\nexport { useBoard } from \"./hooks/useBoard\";\nexport { useGeneration } from \"./hooks/useGeneration\";\nexport { useGenerators } from \"./hooks/useGenerators\";\nexport type { Generator, JSONSchema7 } from \"./hooks/useGenerators\";\n\n// Generator schema utilities\nexport * from \"./types/generatorSchema\";\nexport * from \"./utils/schemaParser\";\n\n// Provider components\nexport { BoardsProvider } from \"./providers/BoardsProvider\";\n"],"mappings":"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","names":["createContext","useContext","jsx","BoardRole","GenerationStatus","ArtifactType","useCallback","useState","useState","useCallback","useCallback","useMemo","useQuery","useMutation","useQuery","useMutation","useMemo","useCallback","useCallback","useState","useEffect","useMutation","useState","useMutation","useEffect","useCallback","result","useMemo","useQuery","useQuery","useMemo","artifactType","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../src/auth/context.tsx","../src/auth/providers/base.ts","../src/auth/providers/none.ts","../src/config/ApiConfigContext.tsx","../src/graphql/client.ts","../src/graphql/operations.ts","../src/hooks/useBoards.ts","../src/hooks/useBoard.ts","../src/hooks/useGeneration.ts","../src/hooks/useGenerators.ts","../src/utils/schemaParser.ts","../src/providers/BoardsProvider.tsx","../src/index.ts"],"sourcesContent":["/**\n * React context for authentication.\n */\n\nimport React, { createContext, useContext, useEffect, useState, useCallback } from 'react';\nimport { AuthContextValue, AuthState } from './types';\nimport { BaseAuthProvider } from './providers/base';\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\ninterface AuthProviderProps {\n provider: BaseAuthProvider;\n children: React.ReactNode;\n}\n\nexport function AuthProvider({ provider, children }: AuthProviderProps) {\n const [state, setState] = useState<AuthState>({\n user: null,\n status: 'loading',\n signIn: async () => {},\n signOut: async () => {},\n getToken: async () => null,\n refreshToken: async () => null,\n });\n const [isInitializing, setIsInitializing] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const clearError = useCallback(() => {\n setError(null);\n }, []);\n\n useEffect(() => {\n let mounted = true;\n let unsubscribe: (() => void) | null = null;\n\n const initializeAuth = async () => {\n try {\n await provider.initialize();\n\n if (!mounted) return;\n\n // Set up state change listener\n unsubscribe = provider.onAuthStateChange((newState) => {\n if (mounted) {\n setState(newState);\n }\n });\n\n // Get initial state\n const initialState = await provider.getAuthState();\n if (mounted) {\n setState(initialState);\n setIsInitializing(false);\n }\n } catch (err) {\n if (mounted) {\n setError(err instanceof Error ? err : new Error('Auth initialization failed'));\n setIsInitializing(false);\n }\n }\n };\n\n initializeAuth();\n\n return () => {\n mounted = false;\n if (unsubscribe) {\n unsubscribe();\n }\n };\n }, [provider]);\n\n // Clean up provider on unmount\n useEffect(() => {\n return () => {\n provider.destroy();\n };\n }, [provider]);\n\n const contextValue: AuthContextValue = {\n ...state,\n isInitializing,\n error,\n clearError,\n };\n\n return (\n <AuthContext.Provider value={contextValue}>\n {children}\n </AuthContext.Provider>\n );\n}\n\nexport function useAuth(): AuthContextValue {\n const context = useContext(AuthContext);\n if (!context) {\n throw new Error('useAuth must be used within an AuthProvider');\n }\n return context;\n}\n\nexport function useAuthOptional(): AuthContextValue | null {\n return useContext(AuthContext);\n}\n","/**\n * Base authentication provider abstract class.\n */\n\nimport { AuthState, User, AuthProviderConfig } from '../types';\n\nexport abstract class BaseAuthProvider {\n protected config: AuthProviderConfig;\n\n constructor(config: AuthProviderConfig = {}) {\n this.config = config;\n }\n\n /**\n * Initialize the auth provider.\n * Called once when the provider is created.\n */\n abstract initialize(): Promise<void>;\n\n /**\n * Get the current authentication state.\n */\n abstract getAuthState(): Promise<AuthState>;\n\n /**\n * Sign in with the provider.\n */\n abstract signIn(opts?: Record<string, unknown>): Promise<void>;\n\n /**\n * Sign out from the provider.\n */\n abstract signOut(): Promise<void>;\n\n /**\n * Get the current authentication token.\n */\n abstract getToken(): Promise<string | null>;\n\n /**\n * Get the current user information.\n */\n abstract getUser(): Promise<User | null>;\n\n /**\n * Listen for auth state changes.\n * Returns an unsubscribe function.\n */\n abstract onAuthStateChange(callback: (state: AuthState) => void): () => void;\n\n /**\n * Clean up resources when the provider is destroyed.\n */\n abstract destroy(): Promise<void>;\n\n /**\n * Get the tenant ID from config.\n */\n protected getTenantId(): string {\n return this.config.tenantId || 'default';\n }\n}\n","/**\n * No-auth provider for local development without authentication.\n */\n\nimport { BaseAuthProvider } from \"./base\";\nimport { AuthState, User, AuthProviderConfig } from \"../types\";\n\ninterface NoAuthConfig extends AuthProviderConfig {\n /**\n * Default user ID for development.\n * Defaults to 'dev-user'.\n */\n defaultUserId?: string;\n\n /**\n * Default user email for development.\n * Defaults to 'dev@example.com'.\n */\n defaultEmail?: string;\n\n /**\n * Default display name for development.\n * Defaults to 'Development User'.\n */\n defaultDisplayName?: string;\n}\n\nexport class NoAuthProvider extends BaseAuthProvider {\n protected config: NoAuthConfig;\n private listeners: ((state: AuthState) => void)[] = [];\n private currentState: AuthState;\n private defaultUser: User;\n\n constructor(config: NoAuthConfig = {}) {\n super(config);\n\n // Production safety check\n const nodeEnv = typeof process !== \"undefined\" ? process.env?.NODE_ENV : \"\";\n const isDevelopment =\n nodeEnv === \"development\" || nodeEnv === \"\" || nodeEnv === \"test\";\n\n if (!isDevelopment) {\n const warning =\n \"NoAuthProvider is being used in a production environment. \" +\n \"This means authentication is disabled! \" +\n \"For production use on a server that is visible to the public, configure a proper authentication provider (JWT, Supabase, Clerk, etc.)\";\n console.warn(\"⚠️ SECURITY WARNING:\", warning);\n }\n\n this.config = {\n defaultUserId: \"dev-user\",\n defaultEmail: \"dev@example.com\",\n defaultDisplayName: \"Development User\",\n ...config,\n };\n\n this.defaultUser = {\n id: this.config.defaultUserId!,\n email: this.config.defaultEmail!,\n name: this.config.defaultDisplayName,\n avatar: undefined,\n metadata: { provider: \"none\" },\n credits: {\n balance: 1000,\n reserved: 0,\n },\n };\n\n this.currentState = {\n user: this.defaultUser,\n status: \"authenticated\", // Always authenticated in no-auth mode\n signIn: this.signIn.bind(this),\n signOut: this.signOut.bind(this),\n getToken: this.getToken.bind(this),\n refreshToken: this.refreshToken.bind(this),\n };\n\n // Use structured warning instead of console.warn\n if (console.warn) {\n console.warn(\n \"🚨 [AUTH] NoAuthProvider is active - authentication is disabled!\",\n {\n message: \"This should ONLY be used in development environments\",\n environment: nodeEnv || \"unknown\",\n provider: \"none\",\n }\n );\n }\n }\n\n async initialize(): Promise<void> {\n // No initialization needed - always authenticated\n this.updateState({ user: this.defaultUser, status: \"authenticated\" });\n }\n\n async getAuthState(): Promise<AuthState> {\n return this.currentState;\n }\n\n async signIn(): Promise<void> {\n // No-op in no-auth mode - already signed in\n if (console.info) {\n console.info(\"[AUTH] SignIn called in no-auth mode - no action taken\", {\n provider: \"none\",\n action: \"signIn\",\n status: \"ignored\",\n });\n }\n }\n\n async signOut(): Promise<void> {\n // No-op in no-auth mode - can't sign out\n if (console.info) {\n console.info(\"[AUTH] SignOut called in no-auth mode - no action taken\", {\n provider: \"none\",\n action: \"signOut\",\n status: \"ignored\",\n });\n }\n }\n\n async getToken(): Promise<string | null> {\n // Return a fake development token\n return \"dev-token|no-auth-mode|always-valid\";\n }\n\n async refreshToken(): Promise<string | null> {\n // Return the same fake token since it doesn't expire\n return \"dev-token|no-auth-mode|always-valid\";\n }\n\n async getUser(): Promise<User | null> {\n return this.defaultUser;\n }\n\n onAuthStateChange(callback: (state: AuthState) => void): () => void {\n // Call immediately with current state\n callback(this.currentState);\n\n this.listeners.push(callback);\n return () => {\n const index = this.listeners.indexOf(callback);\n if (index > -1) {\n this.listeners.splice(index, 1);\n }\n };\n }\n\n async destroy(): Promise<void> {\n this.listeners = [];\n }\n\n private updateState(updates: Partial<AuthState>): void {\n this.currentState = { ...this.currentState, ...updates };\n this.listeners.forEach((listener) => listener(this.currentState));\n }\n}\n","/**\n * API configuration context for providing backend URLs to hooks.\n */\n\nimport { createContext, useContext, ReactNode } from \"react\";\n\nexport interface ApiConfig {\n /**\n * Base URL for the backend API (e.g., \"http://localhost:8088\")\n * Used for REST endpoints like SSE streams\n */\n apiUrl: string;\n /**\n * GraphQL endpoint URL (e.g., \"http://localhost:8088/graphql\")\n */\n graphqlUrl: string;\n /**\n * WebSocket URL for GraphQL subscriptions\n */\n subscriptionUrl?: string;\n}\n\nconst ApiConfigContext = createContext<ApiConfig | null>(null);\n\ninterface ApiConfigProviderProps {\n children: ReactNode;\n config: ApiConfig;\n}\n\nexport function ApiConfigProvider({\n children,\n config,\n}: ApiConfigProviderProps) {\n return (\n <ApiConfigContext.Provider value={config}>\n {children}\n </ApiConfigContext.Provider>\n );\n}\n\nexport function useApiConfig(): ApiConfig {\n const context = useContext(ApiConfigContext);\n if (!context) {\n throw new Error(\"useApiConfig must be used within ApiConfigProvider\");\n }\n return context;\n}\n","/**\n * GraphQL client configuration with authentication.\n */\n\nimport {\n createClient,\n fetchExchange,\n cacheExchange,\n subscriptionExchange,\n makeOperation,\n} from \"urql\";\nimport { authExchange } from \"@urql/exchange-auth\";\nimport { createClient as createWSClient } from \"graphql-ws\";\n\ninterface AuthState {\n getToken(): Promise<string | null>;\n}\n\ninterface ClientConfig {\n url: string;\n subscriptionUrl?: string;\n auth: AuthState;\n tenantId?: string;\n}\n\nexport function createGraphQLClient({\n url,\n subscriptionUrl,\n auth,\n tenantId,\n}: ClientConfig) {\n const wsClient = subscriptionUrl\n ? createWSClient({\n url: subscriptionUrl,\n connectionParams: async () => {\n const token = await auth.getToken();\n const headers: Record<string, string> = {};\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n if (tenantId) {\n headers[\"X-Tenant\"] = tenantId;\n }\n\n return headers;\n },\n })\n : null;\n\n return createClient({\n url,\n exchanges: [\n cacheExchange,\n authExchange(async () => {\n // Initialize auth state by fetching token\n let token = await auth.getToken();\n\n return {\n addAuthToOperation: (operation) => {\n // Build headers\n const headers: Record<string, string> = {};\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n if (tenantId) {\n headers[\"X-Tenant\"] = tenantId;\n }\n const fetchOptions =\n typeof operation.context.fetchOptions === \"function\"\n ? operation.context.fetchOptions()\n : operation.context.fetchOptions || {};\n\n // Add headers to operation context\n return makeOperation(operation.kind, operation, {\n ...operation.context,\n fetchOptions: {\n ...operation.context.fetchOptions,\n headers: {\n ...fetchOptions.headers,\n ...headers,\n },\n },\n });\n },\n\n didAuthError: (error) => {\n // Check if error is auth-related\n return error.graphQLErrors.some(\n (e) =>\n e.extensions?.code === \"UNAUTHENTICATED\" ||\n e.extensions?.code === \"UNAUTHORIZED\"\n );\n },\n\n willAuthError: () => {\n // We don't preemptively block requests\n return false;\n },\n\n refreshAuth: async () => {\n // Re-fetch token on auth error and update the closure variable\n token = await auth.getToken();\n },\n };\n }),\n fetchExchange,\n ...(wsClient\n ? [\n subscriptionExchange({\n forwardSubscription: (operation) => ({\n subscribe: (sink) => ({\n unsubscribe: wsClient.subscribe(\n {\n query: operation.query || \"\",\n variables: operation.variables,\n },\n sink\n ),\n }),\n }),\n }),\n ]\n : []),\n ],\n });\n}\n","/**\n * GraphQL queries and mutations for the Boards API.\n */\n\nimport { gql } from \"urql\";\n\n// Fragments for reusable query parts\nexport const USER_FRAGMENT = gql`\n fragment UserFragment on User {\n id\n email\n displayName\n avatarUrl\n createdAt\n }\n`;\n\nexport const BOARD_FRAGMENT = gql`\n fragment BoardFragment on Board {\n id\n tenantId\n ownerId\n title\n description\n isPublic\n settings\n metadata\n createdAt\n updatedAt\n generationCount\n }\n`;\n\nexport const GENERATION_FRAGMENT = gql`\n fragment GenerationFragment on Generation {\n id\n boardId\n userId\n generatorName\n artifactType\n status\n progress\n storageUrl\n thumbnailUrl\n inputParams\n outputMetadata\n errorMessage\n createdAt\n updatedAt\n completedAt\n }\n`;\n\n// Auth queries\nexport const GET_CURRENT_USER = gql`\n ${USER_FRAGMENT}\n query GetCurrentUser {\n me {\n ...UserFragment\n }\n }\n`;\n\n// Board queries\nexport const GET_BOARDS = gql`\n ${BOARD_FRAGMENT}\n ${USER_FRAGMENT}\n query GetBoards($limit: Int, $offset: Int) {\n myBoards(limit: $limit, offset: $offset) {\n ...BoardFragment\n owner {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const GET_BOARD = gql`\n ${BOARD_FRAGMENT}\n ${USER_FRAGMENT}\n ${GENERATION_FRAGMENT}\n query GetBoard($id: UUID!) {\n board(id: $id) {\n ...BoardFragment\n owner {\n ...UserFragment\n }\n members {\n id\n boardId\n userId\n role\n invitedBy\n joinedAt\n user {\n ...UserFragment\n }\n inviter {\n ...UserFragment\n }\n }\n generations(limit: 10) {\n ...GenerationFragment\n }\n }\n }\n`;\n\n// Generator queries\nexport const GET_GENERATORS = gql`\n query GetGenerators($artifactType: String) {\n generators(artifactType: $artifactType) {\n name\n description\n artifactType\n inputSchema\n }\n }\n`;\n\n// Generation queries\nexport const GET_GENERATIONS = gql`\n ${GENERATION_FRAGMENT}\n query GetGenerations($boardId: UUID, $limit: Int, $offset: Int) {\n generations(boardId: $boardId, limit: $limit, offset: $offset) {\n ...GenerationFragment\n board {\n id\n title\n }\n user {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const GET_GENERATION = gql`\n ${GENERATION_FRAGMENT}\n query GetGeneration($id: UUID!) {\n generation(id: $id) {\n ...GenerationFragment\n board {\n ...BoardFragment\n }\n user {\n ...UserFragment\n }\n }\n }\n`;\n\n// Board mutations\nexport const CREATE_BOARD = gql`\n ${BOARD_FRAGMENT}\n ${USER_FRAGMENT}\n mutation CreateBoard($input: CreateBoardInput!) {\n createBoard(input: $input) {\n ...BoardFragment\n owner {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const UPDATE_BOARD = gql`\n ${BOARD_FRAGMENT}\n mutation UpdateBoard($id: UUID!, $input: UpdateBoardInput!) {\n updateBoard(id: $id, input: $input) {\n ...BoardFragment\n }\n }\n`;\n\nexport const DELETE_BOARD = gql`\n mutation DeleteBoard($id: UUID!) {\n deleteBoard(id: $id) {\n success\n }\n }\n`;\n\n// Board member mutations\nexport const ADD_BOARD_MEMBER = gql`\n mutation AddBoardMember($boardId: UUID!, $email: String!, $role: BoardRole!) {\n addBoardMember(boardId: $boardId, email: $email, role: $role) {\n id\n boardId\n userId\n role\n invitedBy\n joinedAt\n user {\n ...UserFragment\n }\n }\n }\n`;\n\nexport const UPDATE_BOARD_MEMBER_ROLE = gql`\n mutation UpdateBoardMemberRole($id: UUID!, $role: BoardRole!) {\n updateBoardMemberRole(id: $id, role: $role) {\n id\n role\n }\n }\n`;\n\nexport const REMOVE_BOARD_MEMBER = gql`\n mutation RemoveBoardMember($id: UUID!) {\n removeBoardMember(id: $id) {\n success\n }\n }\n`;\n\n// Generation mutations\nexport const CREATE_GENERATION = gql`\n ${GENERATION_FRAGMENT}\n mutation CreateGeneration($input: CreateGenerationInput!) {\n createGeneration(input: $input) {\n ...GenerationFragment\n }\n }\n`;\n\nexport const CANCEL_GENERATION = gql`\n mutation CancelGeneration($id: UUID!) {\n cancelGeneration(id: $id) {\n id\n status\n }\n }\n`;\n\nexport const RETRY_GENERATION = gql`\n ${GENERATION_FRAGMENT}\n mutation RetryGeneration($id: UUID!) {\n retryGeneration(id: $id) {\n ...GenerationFragment\n }\n }\n`;\n\n// Input types (these should match your backend GraphQL schema)\nexport interface CreateBoardInput {\n title: string;\n description?: string;\n isPublic?: boolean;\n settings?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UpdateBoardInput {\n title?: string;\n description?: string;\n isPublic?: boolean;\n settings?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CreateGenerationInput {\n boardId: string;\n generatorName: string;\n artifactType: ArtifactType; // Allow string for flexibility with new types\n inputParams: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\n// Enums (should match backend)\nexport enum BoardRole {\n VIEWER = \"VIEWER\",\n EDITOR = \"EDITOR\",\n ADMIN = \"ADMIN\",\n}\n\nexport enum GenerationStatus {\n PENDING = \"PENDING\",\n RUNNING = \"RUNNING\",\n COMPLETED = \"COMPLETED\",\n FAILED = \"FAILED\",\n CANCELLED = \"CANCELLED\",\n}\n\nexport enum ArtifactType {\n IMAGE = \"image\",\n VIDEO = \"video\",\n AUDIO = \"audio\",\n TEXT = \"text\",\n LORA = \"lora\",\n MODEL = \"model\",\n}\n","/**\n * Hook for managing multiple boards.\n */\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport { useQuery, useMutation } from \"urql\";\n// import { Cache } from '@urql/core';\nimport {\n GET_BOARDS,\n CREATE_BOARD,\n DELETE_BOARD,\n CreateBoardInput,\n} from \"../graphql/operations\";\n\ninterface Board {\n id: string;\n tenantId: string;\n ownerId: string;\n title: string;\n description?: string;\n isPublic: boolean;\n settings: Record<string, unknown>;\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n generationCount: number;\n owner: {\n id: string;\n email: string;\n displayName: string;\n avatarUrl?: string;\n createdAt: string;\n };\n}\n\ninterface UseBoardsOptions {\n limit?: number;\n offset?: number;\n}\n\ninterface BoardsHook {\n boards: Board[];\n loading: boolean;\n error: Error | null;\n createBoard: (data: CreateBoardInput) => Promise<Board>;\n deleteBoard: (boardId: string) => Promise<void>;\n searchBoards: (query: string) => Promise<Board[]>;\n refresh: () => Promise<void>;\n setSearchQuery: (query: string) => void;\n searchQuery: string;\n}\n\nexport function useBoards(options: UseBoardsOptions = {}): BoardsHook {\n const { limit = 50, offset = 0 } = options;\n const [searchQuery, setSearchQuery] = useState(\"\");\n\n // Query for boards\n const [{ data, fetching, error }, reexecuteQuery] = useQuery({\n query: GET_BOARDS,\n variables: { limit, offset },\n });\n\n // Mutations\n const [, createBoardMutation] = useMutation(CREATE_BOARD);\n const [, deleteBoardMutation] = useMutation(DELETE_BOARD);\n\n const boards = useMemo(() => data?.myBoards || [], [data?.myBoards]);\n\n const createBoard = useCallback(\n async (input: CreateBoardInput): Promise<Board> => {\n const result = await createBoardMutation({ input });\n if (result.error) {\n throw new Error(result.error.message);\n }\n if (!result.data?.createBoard) {\n throw new Error(\"Failed to create board\");\n }\n // Refetch boards to update the UI with the new board\n reexecuteQuery({ requestPolicy: \"network-only\" });\n return result.data.createBoard;\n },\n [createBoardMutation, reexecuteQuery]\n );\n\n const deleteBoard = useCallback(\n async (boardId: string): Promise<void> => {\n const result = await deleteBoardMutation({ id: boardId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.deleteBoard?.success) {\n throw new Error(\"Failed to delete board\");\n }\n reexecuteQuery({ requestPolicy: \"network-only\" });\n },\n [deleteBoardMutation, reexecuteQuery]\n );\n\n const searchBoards = useCallback(\n async (query: string): Promise<Board[]> => {\n // Set search query which will trigger debounced search via useEffect\n setSearchQuery(query);\n\n // Return promise that resolves when search completes\n // This is a simplified implementation - in a real app you might want\n // to return the actual search results from the API\n return new Promise((resolve) => {\n // Wait for debounce delay plus a bit more for API response\n setTimeout(() => {\n resolve(\n boards.filter(\n (board: Board) =>\n board.title.toLowerCase().includes(query.toLowerCase()) ||\n board.description?.toLowerCase().includes(query.toLowerCase())\n )\n );\n }, 350);\n });\n },\n [boards]\n );\n\n const refresh = useCallback(async (): Promise<void> => {\n await reexecuteQuery({ requestPolicy: \"network-only\" });\n }, [reexecuteQuery]);\n\n return {\n boards,\n loading: fetching,\n error: error ? new Error(error.message) : null,\n createBoard,\n deleteBoard,\n searchBoards,\n refresh,\n setSearchQuery,\n searchQuery,\n };\n}\n","/**\n * Hook for managing a single board.\n */\n\nimport { useCallback, useMemo } from \"react\";\nimport { useQuery, useMutation } from \"urql\";\nimport { useAuth } from \"../auth/hooks/useAuth\";\nimport {\n GET_BOARD,\n UPDATE_BOARD,\n DELETE_BOARD,\n ADD_BOARD_MEMBER,\n UPDATE_BOARD_MEMBER_ROLE,\n REMOVE_BOARD_MEMBER,\n UpdateBoardInput,\n BoardRole,\n} from \"../graphql/operations\";\n\ninterface User {\n id: string;\n email: string;\n displayName: string;\n avatarUrl?: string;\n createdAt: string;\n}\n\ninterface BoardMember {\n id: string;\n boardId: string;\n userId: string;\n role: BoardRole;\n invitedBy?: string;\n joinedAt: string;\n user: User;\n inviter?: User;\n}\n\ninterface Generation {\n id: string;\n boardId: string;\n userId: string;\n generatorName: string;\n artifactType: string;\n status: string;\n progress: number;\n storageUrl?: string | null;\n thumbnailUrl?: string | null;\n inputParams: Record<string, unknown>;\n outputMetadata: Record<string, unknown>;\n errorMessage?: string | null;\n createdAt: string;\n updatedAt: string;\n completedAt?: string | null;\n}\n\ninterface Board {\n id: string;\n tenantId: string;\n ownerId: string;\n title: string;\n description?: string;\n isPublic: boolean;\n settings: Record<string, unknown>;\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n generationCount: number;\n owner: User;\n members: BoardMember[];\n generations: Generation[];\n}\n\ntype MemberRole = BoardRole;\n\ninterface BoardPermissions {\n canEdit: boolean;\n canDelete: boolean;\n canAddMembers: boolean;\n canRemoveMembers: boolean;\n canGenerate: boolean;\n canExport: boolean;\n}\n\ninterface ShareLinkOptions {\n expiresIn?: number;\n permissions?: string[];\n}\n\ninterface ShareLink {\n id: string;\n url: string;\n expiresAt?: string;\n permissions: string[];\n}\n\ninterface BoardHook {\n board: Board | null;\n members: BoardMember[];\n permissions: BoardPermissions;\n loading: boolean;\n error: Error | null;\n\n // Board operations\n updateBoard: (updates: Partial<UpdateBoardInput>) => Promise<Board>;\n deleteBoard: () => Promise<void>;\n refresh: () => Promise<void>;\n\n // Member management\n addMember: (email: string, role: MemberRole) => Promise<BoardMember>;\n removeMember: (memberId: string) => Promise<void>;\n updateMemberRole: (\n memberId: string,\n role: MemberRole\n ) => Promise<BoardMember>;\n\n // Sharing (placeholder - would need backend implementation)\n generateShareLink: (options: ShareLinkOptions) => Promise<ShareLink>;\n revokeShareLink: (linkId: string) => Promise<void>;\n}\n\nexport function useBoard(boardId: string): BoardHook {\n const { user } = useAuth();\n\n // Query for board data\n const [{ data, fetching, error }, reexecuteQuery] = useQuery({\n query: GET_BOARD,\n variables: { id: boardId },\n pause: !boardId,\n requestPolicy: \"cache-and-network\", // Always fetch fresh data while showing cached data\n });\n\n // Mutations\n const [, updateBoardMutation] = useMutation(UPDATE_BOARD);\n const [, deleteBoardMutation] = useMutation(DELETE_BOARD);\n const [, addMemberMutation] = useMutation(ADD_BOARD_MEMBER);\n const [, updateMemberRoleMutation] = useMutation(UPDATE_BOARD_MEMBER_ROLE);\n const [, removeMemberMutation] = useMutation(REMOVE_BOARD_MEMBER);\n\n const board = useMemo(() => data?.board || null, [data?.board]);\n const members = useMemo(() => board?.members || [], [board?.members]);\n\n // Calculate permissions based on user role\n const permissions = useMemo((): BoardPermissions => {\n if (!board || !user) {\n return {\n canEdit: false,\n canDelete: false,\n canAddMembers: false,\n canRemoveMembers: false,\n canGenerate: false,\n canExport: false,\n };\n }\n\n // Check if user is the board owner\n const isOwner = board.ownerId === user.id;\n\n // Find user's role in board members\n const userMember = members.find(\n (member: BoardMember) => member.userId === user.id\n );\n const userRole = userMember?.role;\n\n const isAdmin = userRole === BoardRole.ADMIN;\n const isEditor = userRole === BoardRole.EDITOR || isAdmin;\n const isViewer = userRole === BoardRole.VIEWER || isEditor;\n\n return {\n canEdit: isOwner || isAdmin || isEditor,\n canDelete: isOwner,\n canAddMembers: isOwner || isAdmin,\n canRemoveMembers: isOwner || isAdmin,\n canGenerate: isOwner || isAdmin || isEditor,\n canExport: isViewer, // Even viewers can export\n };\n }, [board, user, members]);\n\n const updateBoard = useCallback(\n async (updates: Partial<UpdateBoardInput>): Promise<Board> => {\n if (!boardId) {\n throw new Error(\"Board ID is required\");\n }\n\n const result = await updateBoardMutation({\n id: boardId,\n input: updates,\n });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.updateBoard) {\n throw new Error(\"Failed to update board\");\n }\n\n return result.data.updateBoard;\n },\n [boardId, updateBoardMutation]\n );\n\n const deleteBoard = useCallback(async (): Promise<void> => {\n if (!boardId) {\n throw new Error(\"Board ID is required\");\n }\n\n const result = await deleteBoardMutation({ id: boardId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.deleteBoard?.success) {\n throw new Error(\"Failed to delete board\");\n }\n }, [boardId, deleteBoardMutation]);\n\n const addMember = useCallback(\n async (email: string, role: MemberRole): Promise<BoardMember> => {\n if (!boardId) {\n throw new Error(\"Board ID is required\");\n }\n\n const result = await addMemberMutation({\n boardId,\n email,\n role,\n });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.addBoardMember) {\n throw new Error(\"Failed to add member\");\n }\n\n // Refresh board data to get updated members list\n reexecuteQuery({ requestPolicy: \"network-only\" });\n\n return result.data.addBoardMember;\n },\n [boardId, addMemberMutation, reexecuteQuery]\n );\n\n const removeMember = useCallback(\n async (memberId: string): Promise<void> => {\n const result = await removeMemberMutation({ id: memberId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.removeBoardMember?.success) {\n throw new Error(\"Failed to remove member\");\n }\n\n // Refresh board data to get updated members list\n reexecuteQuery({ requestPolicy: \"network-only\" });\n },\n [removeMemberMutation, reexecuteQuery]\n );\n\n const updateMemberRole = useCallback(\n async (memberId: string, role: MemberRole): Promise<BoardMember> => {\n const result = await updateMemberRoleMutation({\n id: memberId,\n role,\n });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.updateBoardMemberRole) {\n throw new Error(\"Failed to update member role\");\n }\n\n // Refresh board data to get updated members list\n reexecuteQuery({ requestPolicy: \"network-only\" });\n\n return result.data.updateBoardMemberRole;\n },\n [updateMemberRoleMutation, reexecuteQuery]\n );\n\n // Placeholder implementations for sharing features\n const generateShareLink = useCallback(\n async (_options: ShareLinkOptions): Promise<ShareLink> => {\n // TODO: Implement share link generation\n throw new Error(\"Share links not implemented yet\");\n },\n []\n );\n\n const revokeShareLink = useCallback(\n async (_linkId: string): Promise<void> => {\n // TODO: Implement share link revocation\n throw new Error(\"Share link revocation not implemented yet\");\n },\n []\n );\n\n const refresh = useCallback(async (): Promise<void> => {\n await reexecuteQuery({ requestPolicy: \"network-only\" });\n }, [reexecuteQuery]);\n\n return {\n board,\n members,\n permissions,\n loading: fetching,\n error: error ? new Error(error.message) : null,\n updateBoard,\n deleteBoard,\n refresh,\n addMember,\n removeMember,\n updateMemberRole,\n generateShareLink,\n revokeShareLink,\n };\n}\n","/**\n * Hook for managing AI generations with real-time progress via SSE.\n */\n\nimport { useCallback, useState, useEffect, useRef } from \"react\";\nimport { fetchEventSource } from \"@microsoft/fetch-event-source\";\nimport { useMutation } from \"urql\";\nimport {\n CREATE_GENERATION,\n CANCEL_GENERATION,\n RETRY_GENERATION,\n CreateGenerationInput,\n ArtifactType,\n} from \"../graphql/operations\";\nimport { useAuth } from \"../auth/context\";\nimport { useApiConfig } from \"../config/ApiConfigContext\";\n\nexport interface GenerationRequest {\n model: string;\n artifactType: ArtifactType; // Allow string for flexibility with new types\n inputs: GenerationInputs;\n boardId: string;\n options?: GenerationOptions;\n}\n\nexport interface GenerationInputs {\n prompt: string;\n negativePrompt?: string;\n image?: string | File;\n mask?: string | File;\n loras?: LoRAInput[];\n seed?: number;\n steps?: number;\n guidance?: number;\n aspectRatio?: string;\n style?: string;\n [key: string]: unknown;\n}\n\nexport interface GenerationOptions {\n priority?: \"low\" | \"normal\" | \"high\";\n timeout?: number;\n webhookUrl?: string;\n [key: string]: unknown;\n}\n\nexport interface LoRAInput {\n id: string;\n weight: number;\n}\n\nexport interface GenerationProgress {\n jobId: string;\n status: \"queued\" | \"processing\" | \"completed\" | \"failed\" | \"cancelled\";\n progress: number; // 0-100\n phase: string;\n message?: string | null;\n estimatedTimeRemaining?: number;\n currentStep?: string;\n logs?: string[];\n}\n\nexport interface GenerationResult {\n id: string;\n jobId: string;\n boardId: string;\n request: GenerationRequest;\n artifacts: Artifact[];\n credits: {\n cost: number;\n balanceBefore: number;\n balance: number;\n };\n performance: {\n queueTime: number;\n processingTime: number;\n totalTime: number;\n };\n createdAt: Date;\n}\n\nexport interface Artifact {\n id: string;\n type: string;\n url: string;\n thumbnailUrl?: string;\n metadata: Record<string, unknown>;\n}\n\nexport interface GenerationHook {\n // Current generation state\n progress: GenerationProgress | null;\n result: GenerationResult | null;\n error: Error | null;\n isGenerating: boolean;\n\n // Operations\n submit: (request: GenerationRequest) => Promise<string>;\n cancel: (jobId: string) => Promise<void>;\n retry: (jobId: string) => Promise<void>;\n\n // History\n history: GenerationResult[];\n clearHistory: () => void;\n}\n\nexport function useGeneration(): GenerationHook {\n const [progress, setProgress] = useState<GenerationProgress | null>(null);\n const [result, setResult] = useState<GenerationResult | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [isGenerating, setIsGenerating] = useState(false);\n const [history, setHistory] = useState<GenerationResult[]>([]);\n\n // Get API configuration and auth\n const { apiUrl } = useApiConfig();\n const auth = useAuth();\n\n // Keep track of active SSE connections (using AbortControllers)\n const abortControllers = useRef<Map<string, AbortController>>(new Map());\n\n // Mutations\n const [, createGenerationMutation] = useMutation(CREATE_GENERATION);\n const [, cancelGenerationMutation] = useMutation(CANCEL_GENERATION);\n const [, retryGenerationMutation] = useMutation(RETRY_GENERATION);\n\n // Clean up SSE connections on unmount\n useEffect(() => {\n return () => {\n abortControllers.current.forEach((controller) => {\n controller.abort();\n });\n abortControllers.current.clear();\n };\n }, []);\n\n const connectToSSE = useCallback(\n async (jobId: string) => {\n // Close existing connection if any\n const existingController = abortControllers.current.get(jobId);\n if (existingController) {\n existingController.abort();\n }\n\n // Create new abort controller\n const abortController = new AbortController();\n abortControllers.current.set(jobId, abortController);\n\n // Get auth token\n const token = await auth.getToken();\n\n // Build headers\n const headers: Record<string, string> = {\n Accept: \"text/event-stream\",\n };\n\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n // Connect to SSE endpoint directly\n const sseUrl = `${apiUrl}/api/sse/generations/${jobId}/progress`;\n console.log(\"SSE: Connecting to\", sseUrl, \"with headers:\", headers);\n\n try {\n await fetchEventSource(sseUrl, {\n headers,\n signal: abortController.signal,\n\n async onopen(response) {\n console.log(\n \"SSE: Connection opened\",\n response.status,\n response.statusText\n );\n if (response.ok) {\n console.log(\"SSE: Connection successful\");\n } else {\n console.error(\"SSE: Connection failed\", response.status);\n throw new Error(`SSE connection failed: ${response.statusText}`);\n }\n },\n\n onmessage(event) {\n console.log(\"SSE: Raw event received:\", event);\n\n // Skip empty messages (like keep-alive comments)\n if (!event.data || event.data.trim() === \"\") {\n console.log(\"SSE: Skipping empty message\");\n return;\n }\n\n try {\n const progressData: GenerationProgress = JSON.parse(event.data);\n console.log(\"SSE: progress data received:\", progressData);\n setProgress(progressData);\n\n // If generation is complete, handle the result\n if (\n progressData.status === \"completed\" ||\n progressData.status === \"failed\" ||\n progressData.status === \"cancelled\"\n ) {\n setIsGenerating(false);\n\n if (progressData.status === \"completed\") {\n // TODO: Fetch the complete result from GraphQL\n // For now, create a mock result\n const mockResult: GenerationResult = {\n id: progressData.jobId,\n jobId: progressData.jobId,\n boardId: \"\", // Would be filled from the original request\n request: {} as GenerationRequest,\n artifacts: [],\n credits: { cost: 0, balanceBefore: 0, balance: 0 },\n performance: {\n queueTime: 0,\n processingTime: 0,\n totalTime: 0,\n },\n createdAt: new Date(),\n };\n\n setResult(mockResult);\n setHistory((prev) => [...prev, mockResult]);\n } else if (progressData.status === \"failed\") {\n setError(new Error(\"Generation failed\"));\n }\n\n // Close connection\n abortController.abort();\n abortControllers.current.delete(jobId);\n }\n } catch (err) {\n console.error(\"Failed to parse SSE message:\", err);\n setError(new Error(\"Failed to parse progress update\"));\n setIsGenerating(false);\n abortController.abort();\n abortControllers.current.delete(jobId);\n }\n },\n\n onerror(err) {\n console.error(\"SSE connection error:\", err);\n console.error(\"SSE error details:\", {\n message: err instanceof Error ? err.message : String(err),\n jobId,\n url: sseUrl,\n });\n setError(new Error(\"Lost connection to generation progress\"));\n setIsGenerating(false);\n abortController.abort();\n abortControllers.current.delete(jobId);\n // Re-throw to stop retry\n throw err;\n },\n\n openWhenHidden: true, // Keep connection open when tab is hidden\n });\n } catch (err) {\n // Connection was aborted or failed\n if (abortController.signal.aborted) {\n console.log(\"SSE connection aborted for job:\", jobId);\n } else {\n console.error(\"SSE connection failed:\", err);\n }\n }\n },\n [apiUrl, auth]\n );\n\n const submit = useCallback(\n async (request: GenerationRequest): Promise<string> => {\n setError(null);\n setProgress(null);\n setResult(null);\n setIsGenerating(true);\n\n // Convert the request to the GraphQL input format\n const input: CreateGenerationInput = {\n boardId: request.boardId,\n generatorName: request.model,\n artifactType: request.artifactType,\n inputParams: {\n ...request.inputs,\n ...request.options,\n },\n };\n\n // Retry logic for generation submission\n let lastError: Error | null = null;\n const maxRetries = 2; // Fewer retries for generation as it's expensive\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n // Submit generation via GraphQL\n const result = await createGenerationMutation({ input });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.createGeneration) {\n throw new Error(\"Failed to create generation\");\n }\n\n const jobId = result.data.createGeneration.id;\n\n // Connect to SSE for progress updates\n connectToSSE(jobId);\n\n // Re-enable the submit button now that submission is complete\n // The SSE connection will continue tracking progress in the background\n setIsGenerating(false);\n\n return jobId;\n } catch (err) {\n lastError =\n err instanceof Error\n ? err\n : new Error(\"Failed to submit generation\");\n\n // Don't retry on certain types of errors\n if (\n lastError.message.includes(\"insufficient credits\") ||\n lastError.message.includes(\"validation\") ||\n lastError.message.includes(\"unauthorized\") ||\n lastError.message.includes(\"forbidden\")\n ) {\n setError(lastError);\n setIsGenerating(false);\n throw lastError;\n }\n\n // If this was the last attempt, throw the error\n if (attempt === maxRetries) {\n setError(lastError);\n setIsGenerating(false);\n throw lastError;\n }\n\n // Wait before retrying (shorter delay for generations)\n await new Promise((resolve) => setTimeout(resolve, 1000 * attempt));\n }\n }\n\n const finalError =\n lastError || new Error(\"Failed to submit generation after retries\");\n setError(finalError);\n setIsGenerating(false);\n throw finalError;\n },\n [createGenerationMutation, connectToSSE]\n );\n\n const cancel = useCallback(\n async (jobId: string): Promise<void> => {\n try {\n // Cancel via GraphQL\n const result = await cancelGenerationMutation({ id: jobId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n // Close SSE connection\n const controller = abortControllers.current.get(jobId);\n if (controller) {\n controller.abort();\n abortControllers.current.delete(jobId);\n }\n\n setIsGenerating(false);\n setProgress((prev) => (prev ? { ...prev, status: \"cancelled\" } : null));\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to cancel generation\")\n );\n }\n },\n [cancelGenerationMutation]\n );\n\n const retry = useCallback(\n async (jobId: string): Promise<void> => {\n try {\n setError(null);\n setIsGenerating(true);\n\n // Retry via GraphQL\n const result = await retryGenerationMutation({ id: jobId });\n\n if (result.error) {\n throw new Error(result.error.message);\n }\n\n if (!result.data?.retryGeneration) {\n throw new Error(\"Failed to retry generation\");\n }\n\n const newJobId = result.data.retryGeneration.id;\n\n // Connect to SSE for the retried job\n connectToSSE(newJobId);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to retry generation\")\n );\n setIsGenerating(false);\n }\n },\n [retryGenerationMutation, connectToSSE]\n );\n\n const clearHistory = useCallback(() => {\n setHistory([]);\n }, []);\n\n return {\n progress,\n result,\n error,\n isGenerating,\n submit,\n cancel,\n retry,\n history,\n clearHistory,\n };\n}\n","/**\n * Hook for fetching available generators.\n */\n\nimport { useMemo } from \"react\";\nimport { useQuery } from \"urql\";\nimport type { JSONSchema7 } from \"json-schema\";\nimport { ArtifactType, GET_GENERATORS } from \"../graphql/operations\";\n\nexport interface Generator {\n name: string;\n description: string;\n artifactType: ArtifactType;\n inputSchema: JSONSchema7;\n}\n\n// Re-export JSONSchema7 for applications\nexport type { JSONSchema7 } from \"json-schema\";\n\ninterface UseGeneratorsOptions {\n artifactType?: string;\n}\n\ninterface GeneratorsHook {\n generators: Generator[];\n loading: boolean;\n error: Error | null;\n}\n\nexport function useGenerators(\n options: UseGeneratorsOptions = {}\n): GeneratorsHook {\n const { artifactType } = options;\n\n // Query for generators\n const [{ data, fetching, error }] = useQuery({\n query: GET_GENERATORS,\n variables: artifactType ? { artifactType } : {},\n });\n\n const generators = useMemo(() => data?.generators || [], [data?.generators]);\n\n return {\n generators,\n loading: fetching,\n error: error ? new Error(error.message) : null,\n };\n}\n","/**\n * Utilities for parsing generator JSON Schemas into structured data\n * suitable for dynamic UI generation.\n */\n\nimport type { JSONSchema7, JSONSchema7Definition } from \"json-schema\";\nimport type {\n ParsedGeneratorSchema,\n ArtifactSlot,\n PromptField,\n SettingsField,\n} from \"../types/generatorSchema\";\n\n/**\n * Checks if a JSON Schema property references an artifact type.\n *\n * Artifacts are identified by $ref paths containing \"Artifact\" in their name,\n * e.g., \"#/$defs/AudioArtifact\" or \"#/$defs/VideoArtifact\".\n *\n * @param property - The JSON Schema property to check\n * @returns True if the property references an artifact type\n */\nexport function isArtifactReference(\n property: JSONSchema7 | JSONSchema7Definition | undefined\n): boolean {\n if (!property || typeof property === \"boolean\") {\n return false;\n }\n\n // Direct $ref to artifact\n if (property.$ref && property.$ref.includes(\"Artifact\")) {\n return true;\n }\n\n // Array with items that reference an artifact\n if (\n property.type === \"array\" &&\n property.items &&\n typeof property.items === \"object\" &&\n !Array.isArray(property.items)\n ) {\n const items = property.items as JSONSchema7;\n return !!(items.$ref && items.$ref.includes(\"Artifact\"));\n }\n\n return false;\n}\n\n/**\n * Extracts the artifact type from a $ref path.\n *\n * Examples:\n * - \"#/$defs/AudioArtifact\" -> \"audio\"\n * - \"#/$defs/VideoArtifact\" -> \"video\"\n * - \"#/$defs/ImageArtifact\" -> \"image\"\n * - \"#/$defs/TextArtifact\" -> \"text\"\n *\n * @param ref - The $ref string from the JSON Schema\n * @returns The artifact type in lowercase\n */\nexport function getArtifactType(\n ref: string\n): \"audio\" | \"video\" | \"image\" | \"text\" {\n const match = ref.match(/(Audio|Video|Image|Text)Artifact/);\n if (match) {\n return match[1].toLowerCase() as \"audio\" | \"video\" | \"image\" | \"text\";\n }\n\n // Fallback to \"image\" if pattern doesn't match\n return \"image\";\n}\n\n/**\n * Parses an artifact property into an ArtifactSlot structure.\n *\n * @param name - The property name from the schema\n * @param property - The JSON Schema property definition\n * @param required - Whether this field is in the required array\n * @returns Parsed artifact slot information\n */\nexport function parseArtifactSlot(\n name: string,\n property: JSONSchema7,\n required: boolean\n): ArtifactSlot {\n const title = property.title || name;\n const description = property.description;\n\n // Check if this is an array of artifacts\n if (property.type === \"array\" && property.items) {\n const items =\n typeof property.items === \"object\" && !Array.isArray(property.items)\n ? (property.items as JSONSchema7)\n : undefined;\n\n const artifactType = items?.$ref ? getArtifactType(items.$ref) : \"image\";\n\n return {\n name: title,\n fieldName: name,\n artifactType,\n required,\n description,\n isArray: true,\n minItems: property.minItems,\n maxItems: property.maxItems,\n };\n }\n\n // Single artifact\n const artifactType = property.$ref ? getArtifactType(property.$ref) : \"image\";\n\n return {\n name: title,\n fieldName: name,\n artifactType,\n required,\n description,\n isArray: false,\n };\n}\n\n/**\n * Determines if a numeric property should be rendered as a slider.\n *\n * A property is considered a slider if it's a number or integer type\n * and has both minimum and maximum values defined.\n *\n * @param property - The JSON Schema property to check\n * @returns True if this should be a slider\n */\nfunction isSlider(property: JSONSchema7): boolean {\n return (\n (property.type === \"number\" || property.type === \"integer\") &&\n property.minimum !== undefined &&\n property.maximum !== undefined\n );\n}\n\n/**\n * Parses a settings field into its appropriate type (slider, dropdown, text, number).\n *\n * @param name - The property name from the schema\n * @param property - The JSON Schema property definition\n * @returns Parsed settings field information\n */\nexport function parseSettingsField(\n name: string,\n property: JSONSchema7\n): SettingsField | null {\n const title = property.title || name;\n const description = property.description;\n\n // Dropdown (enum)\n if (property.enum && Array.isArray(property.enum)) {\n const options = property.enum.map((val) => String(val));\n const defaultValue =\n property.default !== undefined ? String(property.default) : undefined;\n\n return {\n type: \"dropdown\",\n fieldName: name,\n title,\n description,\n options,\n default: defaultValue,\n };\n }\n\n // Slider (number/integer with min/max)\n if (isSlider(property)) {\n const isInteger = property.type === \"integer\";\n return {\n type: \"slider\",\n fieldName: name,\n title,\n description,\n min: property.minimum as number,\n max: property.maximum as number,\n step: property.multipleOf,\n default:\n property.default !== undefined\n ? (property.default as number)\n : undefined,\n isInteger,\n };\n }\n\n // Number input (without slider constraints)\n if (property.type === \"number\" || property.type === \"integer\") {\n const isInteger = property.type === \"integer\";\n return {\n type: \"number\",\n fieldName: name,\n title,\n description,\n default:\n property.default !== undefined\n ? (property.default as number)\n : undefined,\n min: property.minimum as number | undefined,\n max: property.maximum as number | undefined,\n isInteger,\n };\n }\n\n // Text input\n if (property.type === \"string\") {\n return {\n type: \"text\",\n fieldName: name,\n title,\n description,\n default:\n property.default !== undefined ? String(property.default) : undefined,\n pattern: property.pattern,\n };\n }\n\n // Unsupported type\n return null;\n}\n\n/**\n * Parses a complete generator JSON Schema into structured data for UI generation.\n *\n * This function categorizes schema properties into:\n * - Artifact slots (for selecting existing artifacts)\n * - Prompt field (special text input for generation prompts)\n * - Settings fields (sliders, dropdowns, text inputs, etc.)\n *\n * @param schema - The JSON Schema from the generator's inputSchema field\n * @returns Parsed schema structure ready for dynamic UI generation\n *\n * @example\n * ```typescript\n * const generator = generators[0];\n * const parsed = parseGeneratorSchema(generator.inputSchema);\n *\n * // Render artifact slots\n * parsed.artifactSlots.forEach(slot => {\n * console.log(`${slot.name}: ${slot.artifactType} (required: ${slot.required})`);\n * });\n *\n * // Render prompt field\n * if (parsed.promptField) {\n * console.log(`Prompt: ${parsed.promptField.description}`);\n * }\n *\n * // Render settings\n * parsed.settingsFields.forEach(field => {\n * if (field.type === 'slider') {\n * console.log(`${field.title}: ${field.min} - ${field.max}`);\n * }\n * });\n * ```\n */\nexport function parseGeneratorSchema(\n schema: JSONSchema7\n): ParsedGeneratorSchema {\n const artifactSlots: ArtifactSlot[] = [];\n const settingsFields: SettingsField[] = [];\n let promptField: PromptField | null = null;\n\n if (!schema.properties) {\n return { artifactSlots, promptField, settingsFields };\n }\n\n const required = schema.required || [];\n\n for (const [name, propertyDef] of Object.entries(schema.properties)) {\n if (typeof propertyDef === \"boolean\") {\n continue;\n }\n\n const property = propertyDef as JSONSchema7;\n const isRequired = required.includes(name);\n\n // Check if this is an artifact reference\n if (isArtifactReference(property)) {\n const slot = parseArtifactSlot(name, property, isRequired);\n artifactSlots.push(slot);\n continue;\n }\n\n // Check if this is the prompt field\n if (name === \"prompt\" && property.type === \"string\") {\n promptField = {\n fieldName: name,\n description: property.description,\n required: isRequired,\n default:\n property.default !== undefined ? String(property.default) : undefined,\n };\n continue;\n }\n\n // Everything else goes to settings\n const settingsField = parseSettingsField(name, property);\n if (settingsField) {\n settingsFields.push(settingsField);\n }\n }\n\n return {\n artifactSlots,\n promptField,\n settingsFields,\n };\n}\n","/**\n * Main provider component that sets up GraphQL client and auth context.\n */\n\nimport { ReactNode } from \"react\";\nimport { Provider as UrqlProvider } from \"urql\";\nimport { createGraphQLClient } from \"../graphql/client\";\nimport { AuthProvider } from \"../auth/context\";\nimport { BaseAuthProvider } from \"../auth/providers/base\";\nimport { ApiConfigProvider, ApiConfig } from \"../config/ApiConfigContext\";\n\ninterface BoardsProviderProps {\n children: ReactNode;\n /**\n * Base URL for the backend API (e.g., \"http://localhost:8088\")\n * Used for REST endpoints like SSE streams\n */\n apiUrl: string;\n /**\n * GraphQL endpoint URL (e.g., \"http://localhost:8088/graphql\")\n * If not provided, defaults to `${apiUrl}/graphql`\n */\n graphqlUrl?: string;\n /**\n * WebSocket URL for GraphQL subscriptions\n */\n subscriptionUrl?: string;\n authProvider: BaseAuthProvider;\n tenantId?: string;\n}\n\nexport function BoardsProvider({\n children,\n apiUrl,\n graphqlUrl,\n subscriptionUrl,\n authProvider,\n tenantId,\n}: BoardsProviderProps) {\n // Default graphqlUrl if not provided\n const resolvedGraphqlUrl = graphqlUrl || `${apiUrl}/graphql`;\n\n // Create API config for hooks\n const apiConfig: ApiConfig = {\n apiUrl,\n graphqlUrl: resolvedGraphqlUrl,\n subscriptionUrl,\n };\n\n // Create the GraphQL client with auth integration\n const client = createGraphQLClient({\n url: resolvedGraphqlUrl,\n subscriptionUrl,\n auth: {\n getToken: () =>\n authProvider.getAuthState().then((state) => state.getToken()),\n },\n tenantId,\n });\n\n return (\n <AuthProvider provider={authProvider}>\n <ApiConfigProvider config={apiConfig}>\n <UrqlProvider value={client}>{children}</UrqlProvider>\n </ApiConfigProvider>\n </AuthProvider>\n );\n}\n","export const VERSION = \"0.1.0\";\n\n// Core auth exports\nexport * from \"./auth/types\";\nexport * from \"./auth/hooks/useAuth\";\nexport { AuthProvider } from \"./auth/context\";\nexport { BaseAuthProvider } from \"./auth/providers/base\";\nexport { NoAuthProvider } from \"./auth/providers/none\"; // Only no-auth included for dev\n\n// API configuration\nexport { useApiConfig } from \"./config/ApiConfigContext\";\nexport type { ApiConfig } from \"./config/ApiConfigContext\";\n\n// GraphQL exports\nexport { createGraphQLClient } from \"./graphql/client\";\nexport * from \"./graphql/operations\";\n\n// Core hooks\nexport { useBoards } from \"./hooks/useBoards\";\nexport { useBoard } from \"./hooks/useBoard\";\nexport { useGeneration } from \"./hooks/useGeneration\";\nexport { useGenerators } from \"./hooks/useGenerators\";\nexport type { Generator, JSONSchema7 } from \"./hooks/useGenerators\";\n\n// Generator schema utilities\nexport * from \"./types/generatorSchema\";\nexport * from \"./utils/schemaParser\";\n\n// Provider components\nexport { BoardsProvider } from \"./providers/BoardsProvider\";\n"],"mappings":";AAIA,SAAgB,eAAe,YAAY,WAAW,UAAU,mBAAmB;AAmF/E;AA/EJ,IAAM,cAAc,cAAuC,IAAI;AAOxD,SAAS,aAAa,EAAE,UAAU,SAAS,GAAsB;AACtE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAoB;AAAA,IAC5C,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ,YAAY;AAAA,IAAC;AAAA,IACrB,SAAS,YAAY;AAAA,IAAC;AAAA,IACtB,UAAU,YAAY;AAAA,IACtB,cAAc,YAAY;AAAA,EAC5B,CAAC;AACD,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,IAAI;AACzD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAuB,IAAI;AAErD,QAAM,aAAa,YAAY,MAAM;AACnC,aAAS,IAAI;AAAA,EACf,GAAG,CAAC,CAAC;AAEL,YAAU,MAAM;AACd,QAAI,UAAU;AACd,QAAI,cAAmC;AAEvC,UAAM,iBAAiB,YAAY;AACjC,UAAI;AACF,cAAM,SAAS,WAAW;AAE1B,YAAI,CAAC,QAAS;AAGd,sBAAc,SAAS,kBAAkB,CAAC,aAAa;AACrD,cAAI,SAAS;AACX,qBAAS,QAAQ;AAAA,UACnB;AAAA,QACF,CAAC;AAGD,cAAM,eAAe,MAAM,SAAS,aAAa;AACjD,YAAI,SAAS;AACX,mBAAS,YAAY;AACrB,4BAAkB,KAAK;AAAA,QACzB;AAAA,MACF,SAAS,KAAK;AACZ,YAAI,SAAS;AACX,mBAAS,eAAe,QAAQ,MAAM,IAAI,MAAM,4BAA4B,CAAC;AAC7E,4BAAkB,KAAK;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAEA,mBAAe;AAEf,WAAO,MAAM;AACX,gBAAU;AACV,UAAI,aAAa;AACf,oBAAY;AAAA,MACd;AAAA,IACF;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAGb,YAAU,MAAM;AACd,WAAO,MAAM;AACX,eAAS,QAAQ;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,eAAiC;AAAA,IACrC,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SACE,oBAAC,YAAY,UAAZ,EAAqB,OAAO,cAC1B,UACH;AAEJ;AAEO,SAAS,UAA4B;AAC1C,QAAM,UAAU,WAAW,WAAW;AACtC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AACA,SAAO;AACT;AAEO,SAAS,kBAA2C;AACzD,SAAO,WAAW,WAAW;AAC/B;;;ACjGO,IAAe,mBAAf,MAAgC;AAAA,EAGrC,YAAY,SAA6B,CAAC,GAAG;AAC3C,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EA+CU,cAAsB;AAC9B,WAAO,KAAK,OAAO,YAAY;AAAA,EACjC;AACF;;;AClCO,IAAM,iBAAN,cAA6B,iBAAiB;AAAA,EAMnD,YAAY,SAAuB,CAAC,GAAG;AACrC,UAAM,MAAM;AALd,SAAQ,YAA4C,CAAC;AAQnD,UAAM,UAAU,OAAO,YAAY,cAAc,QAAQ,KAAK,WAAW;AACzE,UAAM,gBACJ,YAAY,iBAAiB,YAAY,MAAM,YAAY;AAE7D,QAAI,CAAC,eAAe;AAClB,YAAM,UACJ;AAGF,cAAQ,KAAK,mCAAyB,OAAO;AAAA,IAC/C;AAEA,SAAK,SAAS;AAAA,MACZ,eAAe;AAAA,MACf,cAAc;AAAA,MACd,oBAAoB;AAAA,MACpB,GAAG;AAAA,IACL;AAEA,SAAK,cAAc;AAAA,MACjB,IAAI,KAAK,OAAO;AAAA,MAChB,OAAO,KAAK,OAAO;AAAA,MACnB,MAAM,KAAK,OAAO;AAAA,MAClB,QAAQ;AAAA,MACR,UAAU,EAAE,UAAU,OAAO;AAAA,MAC7B,SAAS;AAAA,QACP,SAAS;AAAA,QACT,UAAU;AAAA,MACZ;AAAA,IACF;AAEA,SAAK,eAAe;AAAA,MAClB,MAAM,KAAK;AAAA,MACX,QAAQ;AAAA;AAAA,MACR,QAAQ,KAAK,OAAO,KAAK,IAAI;AAAA,MAC7B,SAAS,KAAK,QAAQ,KAAK,IAAI;AAAA,MAC/B,UAAU,KAAK,SAAS,KAAK,IAAI;AAAA,MACjC,cAAc,KAAK,aAAa,KAAK,IAAI;AAAA,IAC3C;AAGA,QAAI,QAAQ,MAAM;AAChB,cAAQ;AAAA,QACN;AAAA,QACA;AAAA,UACE,SAAS;AAAA,UACT,aAAa,WAAW;AAAA,UACxB,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAA4B;AAEhC,SAAK,YAAY,EAAE,MAAM,KAAK,aAAa,QAAQ,gBAAgB,CAAC;AAAA,EACtE;AAAA,EAEA,MAAM,eAAmC;AACvC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,SAAwB;AAE5B,QAAI,QAAQ,MAAM;AAChB,cAAQ,KAAK,0DAA0D;AAAA,QACrE,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,UAAyB;AAE7B,QAAI,QAAQ,MAAM;AAChB,cAAQ,KAAK,2DAA2D;AAAA,QACtE,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,WAAmC;AAEvC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,eAAuC;AAE3C,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAgC;AACpC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,kBAAkB,UAAkD;AAElE,aAAS,KAAK,YAAY;AAE1B,SAAK,UAAU,KAAK,QAAQ;AAC5B,WAAO,MAAM;AACX,YAAM,QAAQ,KAAK,UAAU,QAAQ,QAAQ;AAC7C,UAAI,QAAQ,IAAI;AACd,aAAK,UAAU,OAAO,OAAO,CAAC;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,UAAyB;AAC7B,SAAK,YAAY,CAAC;AAAA,EACpB;AAAA,EAEQ,YAAY,SAAmC;AACrD,SAAK,eAAe,EAAE,GAAG,KAAK,cAAc,GAAG,QAAQ;AACvD,SAAK,UAAU,QAAQ,CAAC,aAAa,SAAS,KAAK,YAAY,CAAC;AAAA,EAClE;AACF;;;ACxJA,SAAS,iBAAAA,gBAAe,cAAAC,mBAA6B;AA8BjD,gBAAAC,YAAA;AAZJ,IAAM,mBAAmBF,eAAgC,IAAI;AAOtD,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AACF,GAA2B;AACzB,SACE,gBAAAE,KAAC,iBAAiB,UAAjB,EAA0B,OAAO,QAC/B,UACH;AAEJ;AAEO,SAAS,eAA0B;AACxC,QAAM,UAAUD,YAAW,gBAAgB;AAC3C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACtE;AACA,SAAO;AACT;;;AC1CA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB,sBAAsB;AAaxC,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAiB;AACf,QAAM,WAAW,kBACb,eAAe;AAAA,IACb,KAAK;AAAA,IACL,kBAAkB,YAAY;AAC5B,YAAM,QAAQ,MAAM,KAAK,SAAS;AAClC,YAAM,UAAkC,CAAC;AAEzC,UAAI,OAAO;AACT,gBAAQ,gBAAgB,UAAU,KAAK;AAAA,MACzC;AAEA,UAAI,UAAU;AACZ,gBAAQ,UAAU,IAAI;AAAA,MACxB;AAEA,aAAO;AAAA,IACT;AAAA,EACF,CAAC,IACD;AAEJ,SAAO,aAAa;AAAA,IAClB;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA,aAAa,YAAY;AAEvB,YAAI,QAAQ,MAAM,KAAK,SAAS;AAEhC,eAAO;AAAA,UACL,oBAAoB,CAAC,cAAc;AAEjC,kBAAM,UAAkC,CAAC;AAEzC,gBAAI,OAAO;AACT,sBAAQ,gBAAgB,UAAU,KAAK;AAAA,YACzC;AAEA,gBAAI,UAAU;AACZ,sBAAQ,UAAU,IAAI;AAAA,YACxB;AACA,kBAAM,eACJ,OAAO,UAAU,QAAQ,iBAAiB,aACtC,UAAU,QAAQ,aAAa,IAC/B,UAAU,QAAQ,gBAAgB,CAAC;AAGzC,mBAAO,cAAc,UAAU,MAAM,WAAW;AAAA,cAC9C,GAAG,UAAU;AAAA,cACb,cAAc;AAAA,gBACZ,GAAG,UAAU,QAAQ;AAAA,gBACrB,SAAS;AAAA,kBACP,GAAG,aAAa;AAAA,kBAChB,GAAG;AAAA,gBACL;AAAA,cACF;AAAA,YACF,CAAC;AAAA,UACH;AAAA,UAEA,cAAc,CAAC,UAAU;AAEvB,mBAAO,MAAM,cAAc;AAAA,cACzB,CAAC,MACC,EAAE,YAAY,SAAS,qBACvB,EAAE,YAAY,SAAS;AAAA,YAC3B;AAAA,UACF;AAAA,UAEA,eAAe,MAAM;AAEnB,mBAAO;AAAA,UACT;AAAA,UAEA,aAAa,YAAY;AAEvB,oBAAQ,MAAM,KAAK,SAAS;AAAA,UAC9B;AAAA,QACF;AAAA,MACF,CAAC;AAAA,MACD;AAAA,MACA,GAAI,WACA;AAAA,QACE,qBAAqB;AAAA,UACnB,qBAAqB,CAAC,eAAe;AAAA,YACnC,WAAW,CAAC,UAAU;AAAA,cACpB,aAAa,SAAS;AAAA,gBACpB;AAAA,kBACE,OAAO,UAAU,SAAS;AAAA,kBAC1B,WAAW,UAAU;AAAA,gBACvB;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH,IACA,CAAC;AAAA,IACP;AAAA,EACF,CAAC;AACH;;;AC7HA,SAAS,WAAW;AAGb,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUtB,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBvB,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqB5B,IAAM,mBAAmB;AAAA,IAC5B,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASV,IAAM,aAAa;AAAA,IACtB,cAAc;AAAA,IACd,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWV,IAAM,YAAY;AAAA,IACrB,cAAc;AAAA,IACd,aAAa;AAAA,IACb,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6BhB,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYvB,IAAM,kBAAkB;AAAA,IAC3B,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAehB,IAAM,iBAAiB;AAAA,IAC1B,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAehB,IAAM,eAAe;AAAA,IACxB,cAAc;AAAA,IACd,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWV,IAAM,eAAe;AAAA,IACxB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQX,IAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASrB,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBzB,IAAM,2BAA2B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASjC,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAS5B,IAAM,oBAAoB;AAAA,IAC7B,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQhB,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAS1B,IAAM,mBAAmB;AAAA,IAC5B,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkChB,IAAK,YAAL,kBAAKE,eAAL;AACL,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,WAAQ;AAHE,SAAAA;AAAA,GAAA;AAML,IAAK,mBAAL,kBAAKC,sBAAL;AACL,EAAAA,kBAAA,aAAU;AACV,EAAAA,kBAAA,aAAU;AACV,EAAAA,kBAAA,eAAY;AACZ,EAAAA,kBAAA,YAAS;AACT,EAAAA,kBAAA,eAAY;AALF,SAAAA;AAAA,GAAA;AAQL,IAAK,eAAL,kBAAKC,kBAAL;AACL,EAAAA,cAAA,WAAQ;AACR,EAAAA,cAAA,WAAQ;AACR,EAAAA,cAAA,WAAQ;AACR,EAAAA,cAAA,UAAO;AACP,EAAAA,cAAA,UAAO;AACP,EAAAA,cAAA,WAAQ;AANE,SAAAA;AAAA,GAAA;;;ACzRZ,SAAS,eAAAC,cAAa,SAAS,YAAAC,iBAAgB;AAC/C,SAAS,UAAU,mBAAmB;AA+C/B,SAAS,UAAU,UAA4B,CAAC,GAAe;AACpE,QAAM,EAAE,QAAQ,IAAI,SAAS,EAAE,IAAI;AACnC,QAAM,CAAC,aAAa,cAAc,IAAIC,UAAS,EAAE;AAGjD,QAAM,CAAC,EAAE,MAAM,UAAU,MAAM,GAAG,cAAc,IAAI,SAAS;AAAA,IAC3D,OAAO;AAAA,IACP,WAAW,EAAE,OAAO,OAAO;AAAA,EAC7B,CAAC;AAGD,QAAM,CAAC,EAAE,mBAAmB,IAAI,YAAY,YAAY;AACxD,QAAM,CAAC,EAAE,mBAAmB,IAAI,YAAY,YAAY;AAExD,QAAM,SAAS,QAAQ,MAAM,MAAM,YAAY,CAAC,GAAG,CAAC,MAAM,QAAQ,CAAC;AAEnE,QAAM,cAAcC;AAAA,IAClB,OAAO,UAA4C;AACjD,YAAM,SAAS,MAAM,oBAAoB,EAAE,MAAM,CAAC;AAClD,UAAI,OAAO,OAAO;AAChB,cAAM,IAAI,MAAM,OAAO,MAAM,OAAO;AAAA,MACtC;AACA,UAAI,CAAC,OAAO,MAAM,aAAa;AAC7B,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AAEA,qBAAe,EAAE,eAAe,eAAe,CAAC;AAChD,aAAO,OAAO,KAAK;AAAA,IACrB;AAAA,IACA,CAAC,qBAAqB,cAAc;AAAA,EACtC;AAEA,QAAM,cAAcA;AAAA,IAClB,OAAO,YAAmC;AACxC,YAAM,SAAS,MAAM,oBAAoB,EAAE,IAAI,QAAQ,CAAC;AAExD,UAAI,OAAO,OAAO;AAChB,cAAM,IAAI,MAAM,OAAO,MAAM,OAAO;AAAA,MACtC;AAEA,UAAI,CAAC,OAAO,MAAM,aAAa,SAAS;AACtC,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AACA,qBAAe,EAAE,eAAe,eAAe,CAAC;AAAA,IAClD;AAAA,IACA,CAAC,qBAAqB,cAAc;AAAA,EACtC;AAEA,QAAM,eAAeA;AAAA,IACnB,OAAO,UAAoC;AAEzC,qBAAe,KAAK;AAKpB,aAAO,IAAI,QAAQ,CAAC,YAAY;AAE9B,mBAAW,MAAM;AACf;AAAA,YACE,OAAO;AAAA,cACL,CAAC,UACC,MAAM,MAAM,YAAY,EAAE,SAAS,MAAM,YAAY,CAAC,KACtD,MAAM,aAAa,YAAY,EAAE,SAAS,MAAM,YAAY,CAAC;AAAA,YACjE;AAAA,UACF;AAAA,QACF,GAAG,GAAG;AAAA,MACR,CAAC;AAAA,IACH;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,UAAUA,aAAY,YAA2B;AACrD,UAAM,eAAe,EAAE,eAAe,eAAe,CAAC;AAAA,EACxD,GAAG,CAAC,cAAc,CAAC;AAEnB,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,IACT,OAAO,QAAQ,IAAI,MAAM,MAAM,OAAO,IAAI;AAAA,IAC1C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACvIA,SAAS,eAAAC,cAAa,WAAAC,gBAAe;AACrC,SAAS,YAAAC,WAAU,eAAAC,oBAAmB;AAmH/B,SAAS,SAAS,SAA4B;AACnD,QAAM,EAAE,KAAK,IAAI,QAAQ;AAGzB,QAAM,CAAC,EAAE,MAAM,UAAU,MAAM,GAAG,cAAc,IAAIC,UAAS;AAAA,IAC3D,OAAO;AAAA,IACP,WAAW,EAAE,IAAI,QAAQ;AAAA,IACzB,OAAO,CAAC;AAAA,IACR,eAAe;AAAA;AAAA,EACjB,CAAC;AAGD,QAAM,CAAC,EAAE,mBAAmB,IAAIC,aAAY,YAAY;AACxD,QAAM,CAAC,EAAE,mBAAmB,IAAIA,aAAY,YAAY;AACxD,QAAM,CAAC,EAAE,iBAAiB,IAAIA,aAAY,gBAAgB;AAC1D,QAAM,CAAC,EAAE,wBAAwB,IAAIA,aAAY,wBAAwB;AACzE,QAAM,CAAC,EAAE,oBAAoB,IAAIA,aAAY,mBAAmB;AAEhE,QAAM,QAAQC,SAAQ,MAAM,MAAM,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC;AAC9D,QAAM,UAAUA,SAAQ,MAAM,OAAO,WAAW,CAAC,GAAG,CAAC,OAAO,OAAO,CAAC;AAGpE,QAAM,cAAcA,SAAQ,MAAwB;AAClD,QAAI,CAAC,SAAS,CAAC,MAAM;AACnB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW;AAAA,QACX,eAAe;AAAA,QACf,kBAAkB;AAAA,QAClB,aAAa;AAAA,QACb,WAAW;AAAA,MACb;AAAA,IACF;AAGA,UAAM,UAAU,MAAM,YAAY,KAAK;AAGvC,UAAM,aAAa,QAAQ;AAAA,MACzB,CAAC,WAAwB,OAAO,WAAW,KAAK;AAAA,IAClD;AACA,UAAM,WAAW,YAAY;AAE7B,UAAM,UAAU;AAChB,UAAM,WAAW,sCAAiC;AAClD,UAAM,WAAW,sCAAiC;AAElD,WAAO;AAAA,MACL,SAAS,WAAW,WAAW;AAAA,MAC/B,WAAW;AAAA,MACX,eAAe,WAAW;AAAA,MAC1B,kBAAkB,WAAW;AAAA,MAC7B,aAAa,WAAW,WAAW;AAAA,MACnC,WAAW;AAAA;AAAA,IACb;AAAA,EACF,GAAG,CAAC,OAAO,MAAM,OAAO,CAAC;AAEzB,QAAM,cAAcC;AAAA,IAClB,OAAO,YAAuD;AAC5D,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,sBAAsB;AAAA,MACxC;AAEA,YAAM,SAAS,MAAM,oBAAoB;AAAA,QACvC,IAAI;AAAA,QACJ,OAAO;AAAA,MACT,CAAC;AAED,UAAI,OAAO,OAAO;AAChB,cAAM,IAAI,MAAM,OAAO,MAAM,OAAO;AAAA,MACtC;AAEA,UAAI,CAAC,OAAO,MAAM,aAAa;AAC7B,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AAEA,aAAO,OAAO,KAAK;AAAA,IACrB;AAAA,IACA,CAAC,SAAS,mBAAmB;AAAA,EAC/B;AAEA,QAAM,cAAcA,aAAY,YAA2B;AACzD,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,sBAAsB;AAAA,IACxC;AAEA,UAAM,SAAS,MAAM,oBAAoB,EAAE,IAAI,QAAQ,CAAC;AAExD,QAAI,OAAO,OAAO;AAChB,YAAM,IAAI,MAAM,OAAO,MAAM,OAAO;AAAA,IACtC;AAEA,QAAI,CAAC,OAAO,MAAM,aAAa,SAAS;AACtC,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AAAA,EACF,GAAG,CAAC,SAAS,mBAAmB,CAAC;AAEjC,QAAM,YAAYA;AAAA,IAChB,OAAO,OAAe,SAA2C;AAC/D,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,sBAAsB;AAAA,MACxC;AAEA,YAAM,SAAS,MAAM,kBAAkB;AAAA,QACrC;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,UAAI,OAAO,OAAO;AAChB,cAAM,IAAI,MAAM,OAAO,MAAM,OAAO;AAAA,MACtC;AAEA,UAAI,CAAC,OAAO,MAAM,gBAAgB;AAChC,cAAM,IAAI,MAAM,sBAAsB;AAAA,MACxC;AAGA,qBAAe,EAAE,eAAe,eAAe,CAAC;AAEhD,aAAO,OAAO,KAAK;AAAA,IACrB;AAAA,IACA,CAAC,SAAS,mBAAmB,cAAc;AAAA,EAC7C;AAEA,QAAM,eAAeA;AAAA,IACnB,OAAO,aAAoC;AACzC,YAAM,SAAS,MAAM,qBAAqB,EAAE,IAAI,SAAS,CAAC;AAE1D,UAAI,OAAO,OAAO;AAChB,cAAM,IAAI,MAAM,OAAO,MAAM,OAAO;AAAA,MACtC;AAEA,UAAI,CAAC,OAAO,MAAM,mBAAmB,SAAS;AAC5C,cAAM,IAAI,MAAM,yBAAyB;AAAA,MAC3C;AAGA,qBAAe,EAAE,eAAe,eAAe,CAAC;AAAA,IAClD;AAAA,IACA,CAAC,sBAAsB,cAAc;AAAA,EACvC;AAEA,QAAM,mBAAmBA;AAAA,IACvB,OAAO,UAAkB,SAA2C;AAClE,YAAM,SAAS,MAAM,yBAAyB;AAAA,QAC5C,IAAI;AAAA,QACJ;AAAA,MACF,CAAC;AAED,UAAI,OAAO,OAAO;AAChB,cAAM,IAAI,MAAM,OAAO,MAAM,OAAO;AAAA,MACtC;AAEA,UAAI,CAAC,OAAO,MAAM,uBAAuB;AACvC,cAAM,IAAI,MAAM,8BAA8B;AAAA,MAChD;AAGA,qBAAe,EAAE,eAAe,eAAe,CAAC;AAEhD,aAAO,OAAO,KAAK;AAAA,IACrB;AAAA,IACA,CAAC,0BAA0B,cAAc;AAAA,EAC3C;AAGA,QAAM,oBAAoBA;AAAA,IACxB,OAAO,aAAmD;AAExD,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,kBAAkBA;AAAA,IACtB,OAAO,YAAmC;AAExC,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,UAAUA,aAAY,YAA2B;AACrD,UAAM,eAAe,EAAE,eAAe,eAAe,CAAC;AAAA,EACxD,GAAG,CAAC,cAAc,CAAC;AAEnB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,OAAO,QAAQ,IAAI,MAAM,MAAM,OAAO,IAAI;AAAA,IAC1C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC9TA,SAAS,eAAAC,cAAa,YAAAC,WAAU,aAAAC,YAAW,cAAc;AACzD,SAAS,wBAAwB;AACjC,SAAS,eAAAC,oBAAmB;AAoGrB,SAAS,gBAAgC;AAC9C,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAoC,IAAI;AACxE,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAAkC,IAAI;AAClE,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AACrD,QAAM,CAAC,cAAc,eAAe,IAAIA,UAAS,KAAK;AACtD,QAAM,CAAC,SAAS,UAAU,IAAIA,UAA6B,CAAC,CAAC;AAG7D,QAAM,EAAE,OAAO,IAAI,aAAa;AAChC,QAAM,OAAO,QAAQ;AAGrB,QAAM,mBAAmB,OAAqC,oBAAI,IAAI,CAAC;AAGvE,QAAM,CAAC,EAAE,wBAAwB,IAAIC,aAAY,iBAAiB;AAClE,QAAM,CAAC,EAAE,wBAAwB,IAAIA,aAAY,iBAAiB;AAClE,QAAM,CAAC,EAAE,uBAAuB,IAAIA,aAAY,gBAAgB;AAGhE,EAAAC,WAAU,MAAM;AACd,WAAO,MAAM;AACX,uBAAiB,QAAQ,QAAQ,CAAC,eAAe;AAC/C,mBAAW,MAAM;AAAA,MACnB,CAAC;AACD,uBAAiB,QAAQ,MAAM;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,eAAeC;AAAA,IACnB,OAAO,UAAkB;AAEvB,YAAM,qBAAqB,iBAAiB,QAAQ,IAAI,KAAK;AAC7D,UAAI,oBAAoB;AACtB,2BAAmB,MAAM;AAAA,MAC3B;AAGA,YAAM,kBAAkB,IAAI,gBAAgB;AAC5C,uBAAiB,QAAQ,IAAI,OAAO,eAAe;AAGnD,YAAM,QAAQ,MAAM,KAAK,SAAS;AAGlC,YAAM,UAAkC;AAAA,QACtC,QAAQ;AAAA,MACV;AAEA,UAAI,OAAO;AACT,gBAAQ,gBAAgB,UAAU,KAAK;AAAA,MACzC;AAGA,YAAM,SAAS,GAAG,MAAM,wBAAwB,KAAK;AACrD,cAAQ,IAAI,sBAAsB,QAAQ,iBAAiB,OAAO;AAElE,UAAI;AACF,cAAM,iBAAiB,QAAQ;AAAA,UAC7B;AAAA,UACA,QAAQ,gBAAgB;AAAA,UAExB,MAAM,OAAO,UAAU;AACrB,oBAAQ;AAAA,cACN;AAAA,cACA,SAAS;AAAA,cACT,SAAS;AAAA,YACX;AACA,gBAAI,SAAS,IAAI;AACf,sBAAQ,IAAI,4BAA4B;AAAA,YAC1C,OAAO;AACL,sBAAQ,MAAM,0BAA0B,SAAS,MAAM;AACvD,oBAAM,IAAI,MAAM,0BAA0B,SAAS,UAAU,EAAE;AAAA,YACjE;AAAA,UACF;AAAA,UAEA,UAAU,OAAO;AACf,oBAAQ,IAAI,4BAA4B,KAAK;AAG7C,gBAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,KAAK,MAAM,IAAI;AAC3C,sBAAQ,IAAI,6BAA6B;AACzC;AAAA,YACF;AAEA,gBAAI;AACF,oBAAM,eAAmC,KAAK,MAAM,MAAM,IAAI;AAC9D,sBAAQ,IAAI,gCAAgC,YAAY;AACxD,0BAAY,YAAY;AAGxB,kBACE,aAAa,WAAW,eACxB,aAAa,WAAW,YACxB,aAAa,WAAW,aACxB;AACA,gCAAgB,KAAK;AAErB,oBAAI,aAAa,WAAW,aAAa;AAGvC,wBAAM,aAA+B;AAAA,oBACnC,IAAI,aAAa;AAAA,oBACjB,OAAO,aAAa;AAAA,oBACpB,SAAS;AAAA;AAAA,oBACT,SAAS,CAAC;AAAA,oBACV,WAAW,CAAC;AAAA,oBACZ,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,EAAE;AAAA,oBACjD,aAAa;AAAA,sBACX,WAAW;AAAA,sBACX,gBAAgB;AAAA,sBAChB,WAAW;AAAA,oBACb;AAAA,oBACA,WAAW,oBAAI,KAAK;AAAA,kBACtB;AAEA,4BAAU,UAAU;AACpB,6BAAW,CAAC,SAAS,CAAC,GAAG,MAAM,UAAU,CAAC;AAAA,gBAC5C,WAAW,aAAa,WAAW,UAAU;AAC3C,2BAAS,IAAI,MAAM,mBAAmB,CAAC;AAAA,gBACzC;AAGA,gCAAgB,MAAM;AACtB,iCAAiB,QAAQ,OAAO,KAAK;AAAA,cACvC;AAAA,YACF,SAAS,KAAK;AACZ,sBAAQ,MAAM,gCAAgC,GAAG;AACjD,uBAAS,IAAI,MAAM,iCAAiC,CAAC;AACrD,8BAAgB,KAAK;AACrB,8BAAgB,MAAM;AACtB,+BAAiB,QAAQ,OAAO,KAAK;AAAA,YACvC;AAAA,UACF;AAAA,UAEA,QAAQ,KAAK;AACX,oBAAQ,MAAM,yBAAyB,GAAG;AAC1C,oBAAQ,MAAM,sBAAsB;AAAA,cAClC,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,cACxD;AAAA,cACA,KAAK;AAAA,YACP,CAAC;AACD,qBAAS,IAAI,MAAM,wCAAwC,CAAC;AAC5D,4BAAgB,KAAK;AACrB,4BAAgB,MAAM;AACtB,6BAAiB,QAAQ,OAAO,KAAK;AAErC,kBAAM;AAAA,UACR;AAAA,UAEA,gBAAgB;AAAA;AAAA,QAClB,CAAC;AAAA,MACH,SAAS,KAAK;AAEZ,YAAI,gBAAgB,OAAO,SAAS;AAClC,kBAAQ,IAAI,mCAAmC,KAAK;AAAA,QACtD,OAAO;AACL,kBAAQ,MAAM,0BAA0B,GAAG;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,IAAI;AAAA,EACf;AAEA,QAAM,SAASA;AAAA,IACb,OAAO,YAAgD;AACrD,eAAS,IAAI;AACb,kBAAY,IAAI;AAChB,gBAAU,IAAI;AACd,sBAAgB,IAAI;AAGpB,YAAM,QAA+B;AAAA,QACnC,SAAS,QAAQ;AAAA,QACjB,eAAe,QAAQ;AAAA,QACvB,cAAc,QAAQ;AAAA,QACtB,aAAa;AAAA,UACX,GAAG,QAAQ;AAAA,UACX,GAAG,QAAQ;AAAA,QACb;AAAA,MACF;AAGA,UAAI,YAA0B;AAC9B,YAAM,aAAa;AAEnB,eAAS,UAAU,GAAG,WAAW,YAAY,WAAW;AACtD,YAAI;AAEF,gBAAMC,UAAS,MAAM,yBAAyB,EAAE,MAAM,CAAC;AAEvD,cAAIA,QAAO,OAAO;AAChB,kBAAM,IAAI,MAAMA,QAAO,MAAM,OAAO;AAAA,UACtC;AAEA,cAAI,CAACA,QAAO,MAAM,kBAAkB;AAClC,kBAAM,IAAI,MAAM,6BAA6B;AAAA,UAC/C;AAEA,gBAAM,QAAQA,QAAO,KAAK,iBAAiB;AAG3C,uBAAa,KAAK;AAIlB,0BAAgB,KAAK;AAErB,iBAAO;AAAA,QACT,SAAS,KAAK;AACZ,sBACE,eAAe,QACX,MACA,IAAI,MAAM,6BAA6B;AAG7C,cACE,UAAU,QAAQ,SAAS,sBAAsB,KACjD,UAAU,QAAQ,SAAS,YAAY,KACvC,UAAU,QAAQ,SAAS,cAAc,KACzC,UAAU,QAAQ,SAAS,WAAW,GACtC;AACA,qBAAS,SAAS;AAClB,4BAAgB,KAAK;AACrB,kBAAM;AAAA,UACR;AAGA,cAAI,YAAY,YAAY;AAC1B,qBAAS,SAAS;AAClB,4BAAgB,KAAK;AACrB,kBAAM;AAAA,UACR;AAGA,gBAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,MAAO,OAAO,CAAC;AAAA,QACpE;AAAA,MACF;AAEA,YAAM,aACJ,aAAa,IAAI,MAAM,2CAA2C;AACpE,eAAS,UAAU;AACnB,sBAAgB,KAAK;AACrB,YAAM;AAAA,IACR;AAAA,IACA,CAAC,0BAA0B,YAAY;AAAA,EACzC;AAEA,QAAM,SAASD;AAAA,IACb,OAAO,UAAiC;AACtC,UAAI;AAEF,cAAMC,UAAS,MAAM,yBAAyB,EAAE,IAAI,MAAM,CAAC;AAE3D,YAAIA,QAAO,OAAO;AAChB,gBAAM,IAAI,MAAMA,QAAO,MAAM,OAAO;AAAA,QACtC;AAGA,cAAM,aAAa,iBAAiB,QAAQ,IAAI,KAAK;AACrD,YAAI,YAAY;AACd,qBAAW,MAAM;AACjB,2BAAiB,QAAQ,OAAO,KAAK;AAAA,QACvC;AAEA,wBAAgB,KAAK;AACrB,oBAAY,CAAC,SAAU,OAAO,EAAE,GAAG,MAAM,QAAQ,YAAY,IAAI,IAAK;AAAA,MACxE,SAAS,KAAK;AACZ;AAAA,UACE,eAAe,QAAQ,MAAM,IAAI,MAAM,6BAA6B;AAAA,QACtE;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,wBAAwB;AAAA,EAC3B;AAEA,QAAM,QAAQD;AAAA,IACZ,OAAO,UAAiC;AACtC,UAAI;AACF,iBAAS,IAAI;AACb,wBAAgB,IAAI;AAGpB,cAAMC,UAAS,MAAM,wBAAwB,EAAE,IAAI,MAAM,CAAC;AAE1D,YAAIA,QAAO,OAAO;AAChB,gBAAM,IAAI,MAAMA,QAAO,MAAM,OAAO;AAAA,QACtC;AAEA,YAAI,CAACA,QAAO,MAAM,iBAAiB;AACjC,gBAAM,IAAI,MAAM,4BAA4B;AAAA,QAC9C;AAEA,cAAM,WAAWA,QAAO,KAAK,gBAAgB;AAG7C,qBAAa,QAAQ;AAAA,MACvB,SAAS,KAAK;AACZ;AAAA,UACE,eAAe,QAAQ,MAAM,IAAI,MAAM,4BAA4B;AAAA,QACrE;AACA,wBAAgB,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,IACA,CAAC,yBAAyB,YAAY;AAAA,EACxC;AAEA,QAAM,eAAeD,aAAY,MAAM;AACrC,eAAW,CAAC,CAAC;AAAA,EACf,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACxaA,SAAS,WAAAE,gBAAe;AACxB,SAAS,YAAAC,iBAAgB;AAwBlB,SAAS,cACd,UAAgC,CAAC,GACjB;AAChB,QAAM,EAAE,aAAa,IAAI;AAGzB,QAAM,CAAC,EAAE,MAAM,UAAU,MAAM,CAAC,IAAIC,UAAS;AAAA,IAC3C,OAAO;AAAA,IACP,WAAW,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,EAChD,CAAC;AAED,QAAM,aAAaC,SAAQ,MAAM,MAAM,cAAc,CAAC,GAAG,CAAC,MAAM,UAAU,CAAC;AAE3E,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,IACT,OAAO,QAAQ,IAAI,MAAM,MAAM,OAAO,IAAI;AAAA,EAC5C;AACF;;;ACzBO,SAAS,oBACd,UACS;AACT,MAAI,CAAC,YAAY,OAAO,aAAa,WAAW;AAC9C,WAAO;AAAA,EACT;AAGA,MAAI,SAAS,QAAQ,SAAS,KAAK,SAAS,UAAU,GAAG;AACvD,WAAO;AAAA,EACT;AAGA,MACE,SAAS,SAAS,WAClB,SAAS,SACT,OAAO,SAAS,UAAU,YAC1B,CAAC,MAAM,QAAQ,SAAS,KAAK,GAC7B;AACA,UAAM,QAAQ,SAAS;AACvB,WAAO,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,SAAS,UAAU;AAAA,EACxD;AAEA,SAAO;AACT;AAcO,SAAS,gBACd,KACsC;AACtC,QAAM,QAAQ,IAAI,MAAM,kCAAkC;AAC1D,MAAI,OAAO;AACT,WAAO,MAAM,CAAC,EAAE,YAAY;AAAA,EAC9B;AAGA,SAAO;AACT;AAUO,SAAS,kBACd,MACA,UACA,UACc;AACd,QAAM,QAAQ,SAAS,SAAS;AAChC,QAAM,cAAc,SAAS;AAG7B,MAAI,SAAS,SAAS,WAAW,SAAS,OAAO;AAC/C,UAAM,QACJ,OAAO,SAAS,UAAU,YAAY,CAAC,MAAM,QAAQ,SAAS,KAAK,IAC9D,SAAS,QACV;AAEN,UAAMC,gBAAe,OAAO,OAAO,gBAAgB,MAAM,IAAI,IAAI;AAEjE,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,MACX,cAAAA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,UAAU,SAAS;AAAA,MACnB,UAAU,SAAS;AAAA,IACrB;AAAA,EACF;AAGA,QAAM,eAAe,SAAS,OAAO,gBAAgB,SAAS,IAAI,IAAI;AAEtE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,EACX;AACF;AAWA,SAAS,SAAS,UAAgC;AAChD,UACG,SAAS,SAAS,YAAY,SAAS,SAAS,cACjD,SAAS,YAAY,UACrB,SAAS,YAAY;AAEzB;AASO,SAAS,mBACd,MACA,UACsB;AACtB,QAAM,QAAQ,SAAS,SAAS;AAChC,QAAM,cAAc,SAAS;AAG7B,MAAI,SAAS,QAAQ,MAAM,QAAQ,SAAS,IAAI,GAAG;AACjD,UAAM,UAAU,SAAS,KAAK,IAAI,CAAC,QAAQ,OAAO,GAAG,CAAC;AACtD,UAAM,eACJ,SAAS,YAAY,SAAY,OAAO,SAAS,OAAO,IAAI;AAE9D,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AAGA,MAAI,SAAS,QAAQ,GAAG;AACtB,UAAM,YAAY,SAAS,SAAS;AACpC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,KAAK,SAAS;AAAA,MACd,KAAK,SAAS;AAAA,MACd,MAAM,SAAS;AAAA,MACf,SACE,SAAS,YAAY,SAChB,SAAS,UACV;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAGA,MAAI,SAAS,SAAS,YAAY,SAAS,SAAS,WAAW;AAC7D,UAAM,YAAY,SAAS,SAAS;AACpC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,SACE,SAAS,YAAY,SAChB,SAAS,UACV;AAAA,MACN,KAAK,SAAS;AAAA,MACd,KAAK,SAAS;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAGA,MAAI,SAAS,SAAS,UAAU;AAC9B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,SACE,SAAS,YAAY,SAAY,OAAO,SAAS,OAAO,IAAI;AAAA,MAC9D,SAAS,SAAS;AAAA,IACpB;AAAA,EACF;AAGA,SAAO;AACT;AAoCO,SAAS,qBACd,QACuB;AACvB,QAAM,gBAAgC,CAAC;AACvC,QAAM,iBAAkC,CAAC;AACzC,MAAI,cAAkC;AAEtC,MAAI,CAAC,OAAO,YAAY;AACtB,WAAO,EAAE,eAAe,aAAa,eAAe;AAAA,EACtD;AAEA,QAAM,WAAW,OAAO,YAAY,CAAC;AAErC,aAAW,CAAC,MAAM,WAAW,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AACnE,QAAI,OAAO,gBAAgB,WAAW;AACpC;AAAA,IACF;AAEA,UAAM,WAAW;AACjB,UAAM,aAAa,SAAS,SAAS,IAAI;AAGzC,QAAI,oBAAoB,QAAQ,GAAG;AACjC,YAAM,OAAO,kBAAkB,MAAM,UAAU,UAAU;AACzD,oBAAc,KAAK,IAAI;AACvB;AAAA,IACF;AAGA,QAAI,SAAS,YAAY,SAAS,SAAS,UAAU;AACnD,oBAAc;AAAA,QACZ,WAAW;AAAA,QACX,aAAa,SAAS;AAAA,QACtB,UAAU;AAAA,QACV,SACE,SAAS,YAAY,SAAY,OAAO,SAAS,OAAO,IAAI;AAAA,MAChE;AACA;AAAA,IACF;AAGA,UAAM,gBAAgB,mBAAmB,MAAM,QAAQ;AACvD,QAAI,eAAe;AACjB,qBAAe,KAAK,aAAa;AAAA,IACnC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AChTA,SAAS,YAAY,oBAAoB;AA0DjC,gBAAAC,YAAA;AAhCD,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AAEtB,QAAM,qBAAqB,cAAc,GAAG,MAAM;AAGlD,QAAM,YAAuB;AAAA,IAC3B;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,EACF;AAGA,QAAM,SAAS,oBAAoB;AAAA,IACjC,KAAK;AAAA,IACL;AAAA,IACA,MAAM;AAAA,MACJ,UAAU,MACR,aAAa,aAAa,EAAE,KAAK,CAAC,UAAU,MAAM,SAAS,CAAC;AAAA,IAChE;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE,gBAAAA,KAAC,gBAAa,UAAU,cACtB,0BAAAA,KAAC,qBAAkB,QAAQ,WACzB,0BAAAA,KAAC,gBAAa,OAAO,QAAS,UAAS,GACzC,GACF;AAEJ;;;ACnEO,IAAM,UAAU;","names":["createContext","useContext","jsx","BoardRole","GenerationStatus","ArtifactType","useCallback","useState","useState","useCallback","useCallback","useMemo","useQuery","useMutation","useQuery","useMutation","useMemo","useCallback","useCallback","useState","useEffect","useMutation","useState","useMutation","useEffect","useCallback","result","useMemo","useQuery","useQuery","useMemo","artifactType","jsx"]}
|
package/package.json
CHANGED
package/src/hooks/useBoards.ts
CHANGED
|
@@ -75,9 +75,11 @@ export function useBoards(options: UseBoardsOptions = {}): BoardsHook {
|
|
|
75
75
|
if (!result.data?.createBoard) {
|
|
76
76
|
throw new Error("Failed to create board");
|
|
77
77
|
}
|
|
78
|
+
// Refetch boards to update the UI with the new board
|
|
79
|
+
reexecuteQuery({ requestPolicy: "network-only" });
|
|
78
80
|
return result.data.createBoard;
|
|
79
81
|
},
|
|
80
|
-
[createBoardMutation]
|
|
82
|
+
[createBoardMutation, reexecuteQuery]
|
|
81
83
|
);
|
|
82
84
|
|
|
83
85
|
const deleteBoard = useCallback(
|