@@ -127,31 +127,143 @@ const server = new ApolloServer({ schema, context });
127127
128128### Data Sources
129129
130- Data sources in ` graphql-component ` use a proxy-based approach for context injection:
130+ Data sources in ` graphql-component ` use a proxy-based approach for context injection. The library provides two key types to assist with correct implementation :
131131
132- ``` javascript
133- class PropertyDataSource {
134- async getPropertyById (context , id ) {
135- // context is automatically injected
136- return await this .fetchProperty (id);
132+ ``` typescript
133+ // When implementing a data source:
134+ class MyDataSource implements DataSourceDefinition <MyDataSource > {
135+ name = ' MyDataSource' ;
136+
137+ // Context must be the first parameter when implementing
138+ async getUserById(context : ComponentContext , id : string ) {
139+ // Use context for auth, config, etc.
140+ return { id , name: ' User Name' };
137141 }
138142}
139143
140- // Usage in resolvers
144+ // In resolvers, context is automatically injected:
141145const resolvers = {
142146 Query: {
143- property (_ , { id }, { dataSources }) {
144- return dataSources .PropertyDataSource .getPropertyById (id);
147+ user(_ , { id }, context ) {
148+ // Don't need to pass context - it's injected automatically
149+ return context .dataSources .MyDataSource .getUserById (id );
145150 }
146151 }
147152}
148153
149- // Component configuration
154+ // Add to component:
150155new GraphQLComponent ({
151- dataSources: [new PropertyDataSource ()]
156+ types ,
157+ resolvers ,
158+ dataSources: [new MyDataSource ()]
152159});
153160```
154161
162+ #### Data Source Types
163+
164+ - ` DataSourceDefinition<T> ` : Interface for implementing data sources - methods must accept context as first parameter
165+ - ` DataSource<T> ` : Type representing data sources after proxy wrapping - context is automatically injected
166+
167+ This type system ensures proper context handling while providing a clean API for resolver usage.
168+
169+ #### TypeScript Example
170+
171+ ``` typescript
172+ import {
173+ GraphQLComponent ,
174+ DataSourceDefinition ,
175+ ComponentContext
176+ } from ' graphql-component' ;
177+
178+ // Define your data source with proper types
179+ class UsersDataSource implements DataSourceDefinition <UsersDataSource > {
180+ name = ' users' ;
181+
182+ // Static property
183+ defaultRole = ' user' ;
184+
185+ // Context is required as first parameter when implementing
186+ async getUserById(context : ComponentContext , id : string ): Promise <User > {
187+ // Access context properties (auth, etc.)
188+ const apiKey = context .config ?.apiKey ;
189+
190+ // Implementation details...
191+ return { id , name: ' User Name' , role: this .defaultRole };
192+ }
193+
194+ async getUsersByRole(context : ComponentContext , role : string ): Promise <User []> {
195+ // Implementation details...
196+ return [
197+ { id: ' 1' , name: ' User 1' , role },
198+ { id: ' 2' , name: ' User 2' , role }
199+ ];
200+ }
201+ }
202+
203+ // In resolvers, the context is automatically injected
204+ const resolvers = {
205+ Query: {
206+ user : (_ , { id }, context ) => {
207+ // No need to pass context - it's injected by the proxy
208+ return context .dataSources .users .getUserById (id );
209+ },
210+ usersByRole : (_ , { role }, context ) => {
211+ // No need to pass context - it's injected by the proxy
212+ return context .dataSources .users .getUsersByRole (role );
213+ }
214+ }
215+ };
216+
217+ // Component configuration
218+ const usersComponent = new GraphQLComponent ({
219+ types: `
220+ type User {
221+ id: ID!
222+ name: String!
223+ role: String!
224+ }
225+
226+ type Query {
227+ user(id: ID!): User
228+ usersByRole(role: String!): [User]
229+ }
230+ ` ,
231+ resolvers ,
232+ dataSources: [new UsersDataSource ()]
233+ });
234+ ```
235+
236+ #### Data Source Overrides
237+
238+ You can override data sources when needed (for testing or extending functionality). The override must follow the same interface:
239+
240+ ``` typescript
241+ // For testing - create a mock data source
242+ class MockUsersDataSource implements DataSourceDefinition <UsersDataSource > {
243+ name = ' users' ;
244+ defaultRole = ' admin' ;
245+
246+ async getUserById(context : ComponentContext , id : string ) {
247+ return { id , name: ' Mock User' , role: this .defaultRole };
248+ }
249+
250+ async getUsersByRole(context : ComponentContext , role : string ) {
251+ return [{ id: ' mock' , name: ' Mock User' , role }];
252+ }
253+ }
254+
255+ // Use the component with overrides
256+ const testComponent = new GraphQLComponent ({
257+ imports: [usersComponent ],
258+ dataSourceOverrides: [new MockUsersDataSource ()]
259+ });
260+
261+ // In tests
262+ const context = await testComponent .context ({});
263+ const mockUser = await context .dataSources .users .getUserById (' any-id' );
264+ // mockUser will be { id: 'any-id', name: 'Mock User', role: 'admin' }
265+ ```
266+
155267## Examples
156268
157269The repository includes example implementations:
0 commit comments