@conduit-client/service-bindings-lwc
v3.24.1
Published
Conduit services for LWC bindings
Readme
@conduit-client/service-bindings-lwc
Conduit services for Lightning Web Components (LWC) bindings, providing wire adapter integration for commands.
Overview
This package provides specialized services for integrating Conduit data fetching with Lightning Web Components. It includes wire adapter services for creating LWC-compatible wire adapters from commands, with specialized support for GraphQL queries.
Key Features
- Wire Adapter Support: Service for creating LWC wire adapter constructors from commands
- GraphQL Integration: Specialized GraphQL wire adapter with query validation
- JSON Schema Validation: Configuration validation using JSON schemas
- Subscribable Results: Support for real-time data updates via subscriptions
- Refresh Support: Optional refresh functionality for updating wire data
- Type Safety: Full TypeScript support with proper type definitions
Module Structure
Core Services
LWCWireBindingService
Base wire adapter service for integrating commands with LWC wire adapters.
- Creates wire adapter constructors from commands
- Manages wire adapter lifecycle
- Handles configuration validation with JSON schemas
- Supports subscribable and refreshable results
LWCGraphQLWireBindingService
GraphQL-specific wire adapter service extending the base wire functionality.
- Validates GraphQL operations (queries only, no mutations/subscriptions)
- Maps GraphQL responses to LWC wire format
- Handles GraphQL errors appropriately
- Supports refresh functionality for GraphQL queries
Usage Examples
Basic Wire Adapter
First, create the wire adapter outside your component:
// userDataAdapter.js
import { buildLWCWireBindingsServiceDescriptor } from '@conduit-client/services/bindings-lwc/v1';
// Build the service
const { service: lwcWireBindingsService } = buildLWCWireBindingsServiceDescriptor();
// Define the JSON schema for your wire adapter configuration
const userDataSchema = {
type: 'object',
properties: {
userId: { type: 'string' },
},
required: ['userId'],
additionalProperties: false,
};
// Create a command factory
const getUserDataCommand = (config) => ({
execute: async () => {
// Fetch user data based on config.userId
const response = await fetch(`/api/users/${config.userId}`);
const data = await response.json();
return {
isOk: () => true,
value: {
data: data,
// Optional: Add subscription support
subscribe: (callback) => {
// Set up subscription logic
const interval = setInterval(() => {
// Fetch updated data and call callback
callback({ isOk: () => true, value: { data: updatedData } });
}, 5000);
// Return unsubscribe function
return () => clearInterval(interval);
},
},
};
},
});
// Bind the command to create a wire adapter constructor
export const getUserData = lwcWireBindingsService.bind(
getUserDataCommand,
userDataSchema,
false // Set to true to expose refresh function
);Then use it in your LWC component:
// MyComponent.js
import { LightningElement, wire } from 'lwc';
import { getUserData } from './userDataAdapter';
export default class MyComponent extends LightningElement {
userId = '123';
@wire(getUserData, { userId: '$userId' })
userData;
get formattedData() {
if (this.userData.data) {
return this.userData.data;
}
return undefined;
}
get error() {
return this.userData.error;
}
}GraphQL Wire Adapter
// graphqlAdapter.js
import { buildLWCGraphQLWireBindingsServiceDescriptor } from '@conduit-client/services/bindings-lwc/v1';
import { gql } from '@conduit-client/onestore-graphql-parser/v1';
// Build the GraphQL service
const { service: lwcGraphQLWireBindingsService } = buildLWCGraphQLWireBindingsServiceDescriptor();
// Create a GraphQL command factory
const getGraphQLCommand = (config) => ({
execute: async () => {
// Execute GraphQL query
const response = await fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: config.query,
variables: config.variables,
operationName: config.operationName,
}),
});
const graphqlResponse = await response.json();
return {
isOk: () => !graphqlResponse.errors || graphqlResponse.errors.length === 0,
value: {
data: graphqlResponse,
subscribe: (callback) => {
// Set up GraphQL subscription if needed
return () => {}; // Return unsubscribe
},
},
};
},
});
// Bind to create a GraphQL wire adapter constructor
export const graphqlWire = lwcGraphQLWireBindingsService.bind(
getGraphQLCommand,
undefined, // Schema is handled internally for GraphQL
true // Enable refresh support
);Then use it in your LWC component:
// UserProfile.js
import { LightningElement, wire } from 'lwc';
import { graphqlWire } from './graphqlAdapter';
import { gql } from '@conduit-client/onestore-graphql-parser/v1';
const USER_QUERY = gql`
query GetUser($id: ID!) {
user(id: $id) {
name
email
}
}
`;
export default class UserProfile extends LightningElement {
userId = '123';
@wire(graphqlWire, {
query: USER_QUERY,
variables: '$variables',
operationName: 'GetUser',
})
userData;
get variables() {
return { id: this.userId };
}
get user() {
return this.userData.data?.user;
}
get errors() {
return this.userData.errors;
}
async handleRefresh() {
// If refresh is enabled, you can manually refresh
if (this.userData.refresh) {
await this.userData.refresh();
}
}
}API Reference
Service Descriptors
buildLWCWireBindingsServiceDescriptor()
Returns a service descriptor for creating LWC wire adapters.
const { service } = buildLWCWireBindingsServiceDescriptor();buildLWCGraphQLWireBindingsServiceDescriptor()
Returns a service descriptor for creating GraphQL-specific LWC wire adapters.
const { service } = buildLWCGraphQLWireBindingsServiceDescriptor();Service Methods
bind(getCommand, schema?, exposeRefresh?)
Binds a command factory to create a wire adapter constructor.
Parameters:
getCommand: Function that returns a command object with anexecutemethodschema: Optional JSON schema for configuration validation (required for base wire, optional for GraphQL)exposeRefresh: Optional boolean to expose refresh functionality (default: false)
Returns: A wire adapter constructor class that can be used with LWC's @wire decorator
Wire Adapter Constructor
The constructor returned by bind has the following interface:
class WireAdapterConstructor {
constructor(dataCallback: (result: WireAdapterResult) => void);
connect(): void;
disconnect(): void;
update(config: any): void;
}Wire Adapter Result
The data passed to the LWC component has this shape:
interface WireAdapterResult {
data?: any;
error?: Error;
refresh?: () => Promise<void>; // Only if exposeRefresh is true
}GraphQL-Specific Result
For GraphQL wire adapters, the result follows the GraphQL response format:
interface GraphQLWireResult {
data?: any;
errors?: Array<{
message: string;
locations?: Array<{ line: number; column: number }>;
}>;
refresh?: () => Promise<void>; // Only if exposeRefresh is true
}Command Interface
Commands must implement the interface from @conduit-client/command-base:
Dependencies
@conduit-client/utils: Core utility functions@conduit-client/bindings-utils: Shared binding utilities@conduit-client/jsonschema-validate: JSON schema validation@conduit-client/onestore-graphql-parser: GraphQL parsing utilities
