Apply Composer changes: comprehensive API updates, migrations, middleware, and infrastructure improvements
- Add comprehensive database migrations (001-024) for schema evolution - Enhance API schema with expanded type definitions and resolvers - Add new middleware: audit logging, rate limiting, MFA enforcement, security, tenant auth - Implement new services: AI optimization, billing, blockchain, compliance, marketplace - Add adapter layer for cloud integrations (Cloudflare, Kubernetes, Proxmox, storage) - Update Crossplane provider with enhanced VM management capabilities - Add comprehensive test suite for API endpoints and services - Update frontend components with improved GraphQL subscriptions and real-time updates - Enhance security configurations and headers (CSP, CORS, etc.) - Update documentation and configuration files - Add new CI/CD workflows and validation scripts - Implement design system improvements and UI enhancements
This commit is contained in:
@@ -1,58 +1,69 @@
|
||||
import { ApolloClient, InMemoryCache, createHttpLink, from, ApolloLink } from '@apollo/client'
|
||||
import { setContext } from '@apollo/client/link/context'
|
||||
import { onError } from '@apollo/client/link/error'
|
||||
import { handleApiError, getUserFriendlyMessage } from '@/lib/error-handler'
|
||||
import { ApolloClient, InMemoryCache, split, HttpLink } from '@apollo/client'
|
||||
import { getMainDefinition } from '@apollo/client/utilities'
|
||||
import { GraphQLWsLink } from '@apollo/client/link/subscriptions'
|
||||
import { createClient } from 'graphql-ws'
|
||||
|
||||
// HTTP Link - configured to use the GraphQL API
|
||||
const httpLink = createHttpLink({
|
||||
uri: process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT || 'http://localhost:4000/graphql',
|
||||
const httpLink = new HttpLink({
|
||||
uri: process.env.NEXT_PUBLIC_GRAPHQL_URL || 'http://localhost:4000/graphql',
|
||||
})
|
||||
|
||||
// Auth Link - for adding authentication headers
|
||||
const authLink = setContext((_, { headers }) => {
|
||||
// Get the authentication token from secure storage
|
||||
let token: string | null = null
|
||||
if (typeof window !== 'undefined') {
|
||||
// Try to get from secure storage
|
||||
token = sessionStorage.getItem('auth_token')
|
||||
}
|
||||
|
||||
return {
|
||||
headers: {
|
||||
...headers,
|
||||
authorization: token ? `Bearer ${token}` : '',
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
// Error Link - handle GraphQL and network errors
|
||||
const errorLink = onError(({ graphQLErrors, networkError, operation, forward }) => {
|
||||
if (graphQLErrors) {
|
||||
graphQLErrors.forEach(({ message, locations, path }) => {
|
||||
const error = handleApiError(new Error(message))
|
||||
console.error(
|
||||
`[GraphQL error]: Message: ${getUserFriendlyMessage(error)}, Location: ${locations}, Path: ${path}`
|
||||
// WebSocket link for subscriptions (only in browser)
|
||||
const wsLink =
|
||||
typeof window !== 'undefined'
|
||||
? new GraphQLWsLink(
|
||||
createClient({
|
||||
url: process.env.NEXT_PUBLIC_GRAPHQL_WS_URL || 'ws://localhost:4000/graphql',
|
||||
connectionParams: () => {
|
||||
// Add auth token if available
|
||||
const token = localStorage.getItem('authToken')
|
||||
return token ? { authorization: `Bearer ${token}` } : {}
|
||||
},
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
: null
|
||||
|
||||
if (networkError) {
|
||||
const error = handleApiError(networkError)
|
||||
console.error(`[Network error]: ${getUserFriendlyMessage(error)}`)
|
||||
}
|
||||
})
|
||||
// Split link: use WebSocket for subscriptions, HTTP for queries/mutations
|
||||
const splitLink =
|
||||
typeof window !== 'undefined' && wsLink
|
||||
? split(
|
||||
({ query }) => {
|
||||
const definition = getMainDefinition(query)
|
||||
return (
|
||||
definition.kind === 'OperationDefinition' &&
|
||||
definition.operation === 'subscription'
|
||||
)
|
||||
},
|
||||
wsLink,
|
||||
httpLink
|
||||
)
|
||||
: httpLink
|
||||
|
||||
// Create Apollo Client
|
||||
export const apolloClient = new ApolloClient({
|
||||
link: from([errorLink, authLink, httpLink]),
|
||||
cache: new InMemoryCache(),
|
||||
link: splitLink,
|
||||
cache: new InMemoryCache({
|
||||
typePolicies: {
|
||||
NetworkTopology: {
|
||||
fields: {
|
||||
nodes: {
|
||||
merge(existing = [], incoming) {
|
||||
return incoming
|
||||
},
|
||||
},
|
||||
edges: {
|
||||
merge(existing = [], incoming) {
|
||||
return incoming
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
defaultOptions: {
|
||||
watchQuery: {
|
||||
errorPolicy: 'all',
|
||||
fetchPolicy: 'cache-and-network',
|
||||
},
|
||||
query: {
|
||||
errorPolicy: 'all',
|
||||
fetchPolicy: 'cache-first',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user