Skip to content

Commit 326b9d3

Browse files
committed
Made datasources available on middleware.
1 parent f51a619 commit 326b9d3

File tree

3 files changed

+103
-4
lines changed

3 files changed

+103
-4
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
### v6.0.2
22

3+
- [FIX] DataSources are now available in middleware context, enabling middleware to access component dataSources for authentication and other operations
4+
- [TESTS] Added test to verify dataSources availability in middleware
35
- [PERFORMANCE] Enhanced context building with parallel import processing, and middleware optimization
46
- [TESTS] Added comprehensive performance regression tests to validate optimization correctness and prevent breaking changes
57

src/index.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,14 @@ export default class GraphQLComponent<TContextType extends ComponentContext = Co
184184
this._context = async (globalContext: Record<string, unknown>): Promise<TContextType> => {
185185
//BREAKING: The context injected into data sources won't have data sources on it
186186
const ctx = {
187-
dataSources: this._dataSourceContextInject(globalContext)
187+
dataSources: globalContext.dataSources || {}
188188
};
189189

190+
// Add this component's dataSources if not already present or if empty
191+
if (!globalContext.dataSources || Object.keys(globalContext.dataSources).length === 0) {
192+
Object.assign(ctx.dataSources, this._dataSourceContextInject(globalContext));
193+
}
194+
190195
// Only process imports if they exist
191196
if (this._imports.length > 0) {
192197
// Process imports in parallel if they're independent
@@ -228,7 +233,25 @@ export default class GraphQLComponent<TContextType extends ComponentContext = Co
228233
const contextFn = async (context: Record<string, unknown>): Promise<ComponentContext> => {
229234
debug(`building root context`);
230235

231-
let processedContext = context;
236+
// Inject dataSources early so middleware can access them
237+
const dataSources = this._dataSourceContextInject(context);
238+
239+
// Also gather data sources from imported components for middleware
240+
const importedDataSources = {};
241+
if (this._imports.length > 0) {
242+
for (const { component } of this._imports) {
243+
// Use the public dataSources getter and manually inject them
244+
const componentDataSourcesArray = component.dataSources;
245+
const componentDataSourceOverrides = component.dataSourceOverrides;
246+
const componentInjector = createDataSourceContextInjector(componentDataSourcesArray, componentDataSourceOverrides);
247+
const componentDataSources = componentInjector(context);
248+
Object.assign(importedDataSources, componentDataSources);
249+
}
250+
}
251+
252+
// Combine all data sources for middleware
253+
const allDataSources = Object.assign({}, dataSources, importedDataSources);
254+
let processedContext = Object.assign({}, context, { dataSources: allDataSources });
232255

233256
// Apply middleware more efficiently
234257
if (this._middleware.length > 0) {
@@ -258,8 +281,6 @@ export default class GraphQLComponent<TContextType extends ComponentContext = Co
258281
return contextFn;
259282
}
260283

261-
262-
263284
get name(): string {
264285
return this.constructor.name;
265286
}

test/context.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,81 @@ test('GraphQLComponent Context Tests', (t) => {
3838
assert.end();
3939
});
4040

41+
t.test('should have dataSources available in middleware', async (assert) => {
42+
class TestDataSource {
43+
name = 'TestDataSource';
44+
45+
getData(context: any, id: string) {
46+
return { id, fromDataSource: true };
47+
}
48+
}
49+
50+
const component = new GraphQLComponent({
51+
types: `type Query { test: String }`,
52+
dataSources: [new TestDataSource()]
53+
});
54+
55+
let middlewareDataSources: any = null;
56+
const contextFn = component.context;
57+
contextFn.use('dataSourceTest', async (ctx) => {
58+
middlewareDataSources = ctx.dataSources;
59+
return {
60+
...ctx,
61+
middlewareRan: true
62+
};
63+
});
64+
65+
const context = await contextFn({});
66+
67+
assert.ok(middlewareDataSources, 'dataSources available in middleware');
68+
assert.ok(middlewareDataSources.TestDataSource, 'TestDataSource available in middleware');
69+
assert.equal(typeof middlewareDataSources.TestDataSource.getData, 'function', 'dataSource method available');
70+
assert.ok(context.middlewareRan, 'middleware executed');
71+
assert.end();
72+
});
73+
74+
t.test('should preserve imported dataSources in context', async (assert) => {
75+
class ImportedDataSource {
76+
name = 'ImportedDataSource';
77+
78+
getImportedData(context: any, id: string) {
79+
return { id, fromImportedDataSource: true };
80+
}
81+
}
82+
83+
class LocalDataSource {
84+
name = 'LocalDataSource';
85+
86+
getLocalData(context: any, id: string) {
87+
return { id, fromLocalDataSource: true };
88+
}
89+
}
90+
91+
const importedComponent = new GraphQLComponent({
92+
types: `type ImportedQuery { imported: String }`,
93+
dataSources: [new ImportedDataSource()]
94+
});
95+
96+
const mainComponent = new GraphQLComponent({
97+
types: `type Query { local: String }`,
98+
dataSources: [new LocalDataSource()],
99+
imports: [importedComponent]
100+
});
101+
102+
const context = await mainComponent.context({});
103+
104+
assert.ok(context.dataSources, 'dataSources available in context');
105+
106+
// Check that imported dataSource is available
107+
assert.ok(context.dataSources.ImportedDataSource, 'ImportedDataSource available in context');
108+
assert.equal(typeof context.dataSources.ImportedDataSource.getImportedData, 'function', 'imported dataSource method available');
109+
110+
// Check that local dataSource is also available
111+
assert.ok(context.dataSources.LocalDataSource, 'LocalDataSource available in context');
112+
assert.equal(typeof context.dataSources.LocalDataSource.getLocalData, 'function', 'local dataSource method available');
113+
114+
assert.end();
115+
});
116+
41117
t.end();
42118
});

0 commit comments

Comments
 (0)